From de39af7f65c55f79884ecacbf93ef115b3ac84b3 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Fri, 19 May 2017 14:48:00 -0700 Subject: [PATCH] tilelink2: make some Xbar methods reusable --- src/main/scala/uncore/tilelink2/Xbar.scala | 101 +++++++++++---------- 1 file changed, 52 insertions(+), 49 deletions(-) diff --git a/src/main/scala/uncore/tilelink2/Xbar.scala b/src/main/scala/uncore/tilelink2/Xbar.scala index f394debb..d314bf58 100644 --- a/src/main/scala/uncore/tilelink2/Xbar.scala +++ b/src/main/scala/uncore/tilelink2/Xbar.scala @@ -8,34 +8,6 @@ import diplomacy._ class TLXbar(policy: TLArbiter.Policy = TLArbiter.lowestIndexFirst)(implicit p: Parameters) extends LazyModule { - def mapInputIds (ports: Seq[TLClientPortParameters ]) = assignRanges(ports.map(_.endSourceId)).map(_.get) - def mapOutputIds(ports: Seq[TLManagerPortParameters]) = assignRanges(ports.map(_.endSinkId)) - - def assignRanges(sizes: Seq[Int]) = { - val pow2Sizes = sizes.map { z => if (z == 0) 0 else 1 << log2Ceil(z) } - val tuples = pow2Sizes.zipWithIndex.sortBy(_._1) // record old index, then sort by increasing size - val starts = tuples.scanRight(0)(_._1 + _).tail // suffix-sum of the sizes = the start positions - val ranges = (tuples zip starts) map { case ((sz, i), st) => - (if (sz == 0) None else Some(IdRange(st, st+sz)), i) - } - ranges.sortBy(_._2).map(_._1) // Restore orignal order - } - - def relabeler() = { - var idFactory = 0 - () => { - val fifoMap = scala.collection.mutable.HashMap.empty[Int, Int] - (x: Int) => { - if (fifoMap.contains(x)) fifoMap(x) else { - val out = idFactory - idFactory = idFactory + 1 - fifoMap += (x -> out) - out - } - } - } - } - val node = TLNexusNode( numClientPorts = 1 to 32, numManagerPorts = 1 to 32, @@ -44,7 +16,7 @@ class TLXbar(policy: TLArbiter.Policy = TLArbiter.lowestIndexFirst)(implicit p: "An unsafe atomic port can not be combined with any other!") seq(0).copy( minLatency = seq.map(_.minLatency).min, - clients = (mapInputIds(seq) zip seq) flatMap { case (range, port) => + clients = (TLXbar.mapInputIds(seq) zip seq) flatMap { case (range, port) => port.clients map { client => client.copy( sourceId = client.sourceId.shift(range.start) )} @@ -52,8 +24,8 @@ class TLXbar(policy: TLArbiter.Policy = TLArbiter.lowestIndexFirst)(implicit p: ) }, managerFn = { seq => - val fifoIdFactory = relabeler() - val outputIdRanges = mapOutputIds(seq) + val fifoIdFactory = TLXbar.relabeler() + val outputIdRanges = TLXbar.mapOutputIds(seq) seq(0).copy( minLatency = seq.map(_.minLatency).min, endSinkId = outputIdRanges.map(_.map(_.end).getOrElse(0)).max, @@ -75,8 +47,8 @@ class TLXbar(policy: TLArbiter.Policy = TLArbiter.lowestIndexFirst)(implicit p: } // Grab the port ID mapping - val inputIdRanges = mapInputIds(node.edgesIn.map(_.client)) - val outputIdRanges = mapOutputIds(node.edgesOut.map(_.manager)) + val inputIdRanges = TLXbar.mapInputIds(node.edgesIn.map(_.client)) + val outputIdRanges = TLXbar.mapOutputIds(node.edgesOut.map(_.manager)) // Find a good mask for address decoding val port_addrs = node.edgesOut.map(_.manager.managers.map(_.address).flatten) @@ -170,23 +142,12 @@ class TLXbar(policy: TLArbiter.Policy = TLArbiter.lowestIndexFirst)(implicit p: def transpose[T](x: Seq[Seq[T]]) = Seq.tabulate(x(0).size) { i => Seq.tabulate(x.size) { j => x(j)(i) } } def filter[T](data: Seq[T], mask: Seq[Boolean]) = (data zip mask).filter(_._2).map(_._1) - // Replicate an input port to each output port - def fanout[T <: TLChannel](input: DecoupledIO[T], select: Seq[Bool]) = { - val filtered = Wire(Vec(select.size, input)) - for (i <- 0 until select.size) { - filtered(i).bits := input.bits - filtered(i).valid := input.valid && select(i) - } - input.ready := Mux1H(select, filtered.map(_.ready)) - filtered - } - // Fanout the input sources to the output sinks - val portsAOI = transpose((in zip requestAIO) map { case (i, r) => fanout(i.a, r) }) - val portsBIO = transpose((out zip requestBOI) map { case (o, r) => fanout(o.b, r) }) - val portsCOI = transpose((in zip requestCIO) map { case (i, r) => fanout(i.c, r) }) - val portsDIO = transpose((out zip requestDOI) map { case (o, r) => fanout(o.d, r) }) - val portsEOI = transpose((in zip requestEIO) map { case (i, r) => fanout(i.e, r) }) + val portsAOI = transpose((in zip requestAIO) map { case (i, r) => TLXbar.fanout(i.a, r) }) + val portsBIO = transpose((out zip requestBOI) map { case (o, r) => TLXbar.fanout(o.b, r) }) + val portsCOI = transpose((in zip requestCIO) map { case (i, r) => TLXbar.fanout(i.c, r) }) + val portsDIO = transpose((out zip requestDOI) map { case (o, r) => TLXbar.fanout(o.d, r) }) + val portsEOI = transpose((in zip requestEIO) map { case (i, r) => TLXbar.fanout(i.e, r) }) // Arbitrate amongst the sources for (o <- 0 until out.size) { @@ -210,6 +171,48 @@ class TLXbar(policy: TLArbiter.Policy = TLArbiter.lowestIndexFirst)(implicit p: } } +object TLXbar +{ + def mapInputIds (ports: Seq[TLClientPortParameters ]) = assignRanges(ports.map(_.endSourceId)).map(_.get) + def mapOutputIds(ports: Seq[TLManagerPortParameters]) = assignRanges(ports.map(_.endSinkId)) + + def assignRanges(sizes: Seq[Int]) = { + val pow2Sizes = sizes.map { z => if (z == 0) 0 else 1 << log2Ceil(z) } + val tuples = pow2Sizes.zipWithIndex.sortBy(_._1) // record old index, then sort by increasing size + val starts = tuples.scanRight(0)(_._1 + _).tail // suffix-sum of the sizes = the start positions + val ranges = (tuples zip starts) map { case ((sz, i), st) => + (if (sz == 0) None else Some(IdRange(st, st+sz)), i) + } + ranges.sortBy(_._2).map(_._1) // Restore orignal order + } + + def relabeler() = { + var idFactory = 0 + () => { + val fifoMap = scala.collection.mutable.HashMap.empty[Int, Int] + (x: Int) => { + if (fifoMap.contains(x)) fifoMap(x) else { + val out = idFactory + idFactory = idFactory + 1 + fifoMap += (x -> out) + out + } + } + } + } + + // Replicate an input port to each output port + def fanout[T <: TLChannel](input: DecoupledIO[T], select: Seq[Bool]) = { + val filtered = Wire(Vec(select.size, input)) + for (i <- 0 until select.size) { + filtered(i).bits := input.bits + filtered(i).valid := input.valid && select(i) + } + input.ready := Mux1H(select, filtered.map(_.ready)) + filtered + } +} + /** Synthesizeable unit tests */ import unittest._