tilelink2: make some Xbar methods reusable
This commit is contained in:
		@@ -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._
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user