Address Map refactoring
This commit is contained in:
		@@ -32,25 +32,30 @@ trait HasAddrMapParameters {
 | 
			
		||||
  val addrMap = new AddrHashMap(p(GlobalAddrMap))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
case class MemAttr(prot: Int, cacheable: Boolean = false)
 | 
			
		||||
 | 
			
		||||
abstract class MemRegion {
 | 
			
		||||
  def align: BigInt
 | 
			
		||||
  def size: BigInt
 | 
			
		||||
  def numSlaves: Int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
case class MemSize(size: BigInt, prot: Int, cacheable: Boolean = false) extends MemRegion {
 | 
			
		||||
case class MemSize(size: BigInt, align: BigInt, attr: MemAttr) extends MemRegion {
 | 
			
		||||
  def numSlaves = 1
 | 
			
		||||
}
 | 
			
		||||
case class MemSubmap(size: BigInt, entries: AddrMap) extends MemRegion {
 | 
			
		||||
  val numSlaves = entries.countSlaves
 | 
			
		||||
  val align = entries.computeAlign
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
object AddrMapConsts {
 | 
			
		||||
object AddrMapProt {
 | 
			
		||||
  val R = 0x1
 | 
			
		||||
  val W = 0x2
 | 
			
		||||
  val X = 0x4
 | 
			
		||||
  val RW = R | W
 | 
			
		||||
  val RX = R | X
 | 
			
		||||
  val RWX = R | W | X
 | 
			
		||||
  val SZ = 3
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class AddrMapProt extends Bundle {
 | 
			
		||||
@@ -61,15 +66,21 @@ class AddrMapProt extends Bundle {
 | 
			
		||||
 | 
			
		||||
case class AddrMapEntry(name: String, region: MemRegion)
 | 
			
		||||
 | 
			
		||||
case class AddrHashMapEntry(port: Int, start: BigInt, size: BigInt, prot: Int, cacheable: Boolean)
 | 
			
		||||
case class AddrHashMapEntry(port: Int, start: BigInt, region: MemRegion)
 | 
			
		||||
 | 
			
		||||
class AddrMap(entries: Seq[AddrMapEntry]) extends scala.collection.IndexedSeq[AddrMapEntry] {
 | 
			
		||||
  private val hash = HashMap(entries.map(e => (e.name, e.region)):_*)
 | 
			
		||||
 | 
			
		||||
  def apply(index: Int): AddrMapEntry = entries(index)
 | 
			
		||||
 | 
			
		||||
  def length: Int = entries.size
 | 
			
		||||
 | 
			
		||||
  def countSlaves: Int = entries.map(_.region.numSlaves).foldLeft(0)(_ + _)
 | 
			
		||||
 | 
			
		||||
  def computeSize: BigInt = new AddrHashMap(this).size
 | 
			
		||||
 | 
			
		||||
  def computeAlign: BigInt = entries.map(_.region.align).foldLeft(BigInt(1))(_ max _)
 | 
			
		||||
 | 
			
		||||
  override def tail: AddrMap = new AddrMap(entries.tail)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -78,68 +89,68 @@ object AddrMap {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class AddrHashMap(addrmap: AddrMap, start: BigInt = BigInt(0)) {
 | 
			
		||||
  val mapping = new HashMap[String, AddrHashMapEntry]
 | 
			
		||||
  private val mapping = HashMap[String, AddrHashMapEntry]()
 | 
			
		||||
  private val subMaps = HashMap[String, AddrHashMapEntry]()
 | 
			
		||||
 | 
			
		||||
  private def genPairs(am: AddrMap, start: BigInt): Seq[(String, AddrHashMapEntry)] = {
 | 
			
		||||
    var ind = 0
 | 
			
		||||
  private def genPairs(am: AddrMap, start: BigInt, startIdx: Int, prefix: String): (BigInt, Int) = {
 | 
			
		||||
    var ind = startIdx
 | 
			
		||||
    var base = start
 | 
			
		||||
    var pairs = Seq[(String, AddrHashMapEntry)]()
 | 
			
		||||
    am.foreach {
 | 
			
		||||
      case AddrMapEntry(name, MemSize(size, prot, cacheable)) =>
 | 
			
		||||
        pairs = (name, AddrHashMapEntry(ind, base, size, prot, cacheable)) +: pairs
 | 
			
		||||
        base += size
 | 
			
		||||
    am.foreach { ame =>
 | 
			
		||||
      val name = prefix + ame.name
 | 
			
		||||
      base = (base + ame.region.align - 1) / ame.region.align * ame.region.align
 | 
			
		||||
      ame.region match {
 | 
			
		||||
      case r: MemSize =>
 | 
			
		||||
        mapping += name -> AddrHashMapEntry(ind, base, r)
 | 
			
		||||
        base += r.size
 | 
			
		||||
        ind += 1
 | 
			
		||||
      case AddrMapEntry(name, MemSubmap(size, submap)) =>
 | 
			
		||||
        val subpairs = genPairs(submap, base).map {
 | 
			
		||||
          case (subname, AddrHashMapEntry(subind, subbase, subsize, prot, cacheable)) =>
 | 
			
		||||
            (name + ":" + subname,
 | 
			
		||||
              AddrHashMapEntry(ind + subind, subbase, subsize, prot, cacheable))
 | 
			
		||||
        }
 | 
			
		||||
        pairs = subpairs ++ pairs
 | 
			
		||||
        ind += subpairs.size
 | 
			
		||||
        base += size
 | 
			
		||||
    }
 | 
			
		||||
    pairs
 | 
			
		||||
      case r: MemSubmap =>
 | 
			
		||||
        subMaps += name -> AddrHashMapEntry(-1, base, r)
 | 
			
		||||
        ind = genPairs(r.entries, base, ind, name + ":")._2
 | 
			
		||||
        base += r.size
 | 
			
		||||
    }}
 | 
			
		||||
    (base, ind)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for ((name, ind) <- genPairs(addrmap, start)) { mapping(name) = ind }
 | 
			
		||||
  val size = genPairs(addrmap, start, 0, "")._1
 | 
			
		||||
 | 
			
		||||
  def nEntries: Int = mapping.size
 | 
			
		||||
  def apply(name: String): AddrHashMapEntry = mapping(name)
 | 
			
		||||
  def get(name: String): Option[AddrHashMapEntry] = mapping.get(name)
 | 
			
		||||
  def sortedEntries(): Seq[(String, BigInt, BigInt, Int, Boolean)] = {
 | 
			
		||||
    val arr = new Array[(String, BigInt, BigInt, Int, Boolean)](mapping.size)
 | 
			
		||||
    mapping.foreach { case (name, AddrHashMapEntry(port, base, size, prot, cacheable)) =>
 | 
			
		||||
      arr(port) = (name, base, size, prot, cacheable)
 | 
			
		||||
  val sortedEntries: Seq[(String, BigInt, MemSize)] = {
 | 
			
		||||
    val arr = new Array[(String, BigInt, MemSize)](mapping.size)
 | 
			
		||||
    mapping.foreach { case (name, AddrHashMapEntry(port, base, region)) =>
 | 
			
		||||
      arr(port) = (name, base, region.asInstanceOf[MemSize])
 | 
			
		||||
    }
 | 
			
		||||
    arr.toSeq
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def nEntries: Int = mapping.size
 | 
			
		||||
  def apply(name: String): AddrHashMapEntry = mapping.getOrElse(name, subMaps(name))
 | 
			
		||||
  def subMap(name: String): (BigInt, AddrMap) = {
 | 
			
		||||
    val m = subMaps(name)
 | 
			
		||||
    (m.start, m.region.asInstanceOf[MemSubmap].entries)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def isInRegion(name: String, addr: UInt): Bool = {
 | 
			
		||||
    val start = mapping(name).start
 | 
			
		||||
    val size = mapping(name).size
 | 
			
		||||
    val size = mapping(name).region.size
 | 
			
		||||
    UInt(start) <= addr && addr < UInt(start + size)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def isCacheable(addr: UInt): Bool = {
 | 
			
		||||
    sortedEntries().map { case (_, base, size, _, cacheable) =>
 | 
			
		||||
      UInt(base) <= addr && addr < UInt(base + size) && Bool(cacheable)
 | 
			
		||||
    }.reduce(_ || _)
 | 
			
		||||
    sortedEntries.filter(_._3.attr.cacheable).map { case (_, base, region) =>
 | 
			
		||||
      UInt(base) <= addr && addr < UInt(base + region.size)
 | 
			
		||||
    }.foldLeft(Bool(false))(_ || _)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def isValid(addr: UInt): Bool = {
 | 
			
		||||
    addr < UInt(start) || sortedEntries().map {
 | 
			
		||||
      case (_, base, size, _, _) =>
 | 
			
		||||
        addr >= UInt(base) && addr < UInt(base + size)
 | 
			
		||||
    }.reduceLeft(_ || _)
 | 
			
		||||
    sortedEntries.map { case (_, base, region) =>
 | 
			
		||||
      addr >= UInt(base) && addr < UInt(base + region.size)
 | 
			
		||||
    }.foldLeft(Bool(false))(_ || _)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def getProt(addr: UInt): AddrMapProt = {
 | 
			
		||||
    val protBits = Mux(addr < UInt(start),
 | 
			
		||||
      Bits(AddrMapConsts.RWX, 3),
 | 
			
		||||
      Mux1H(sortedEntries().map { case (_, base, size, prot, _) =>
 | 
			
		||||
        (addr >= UInt(base) && addr < UInt(base + size), Bits(prot, 3))
 | 
			
		||||
      }))
 | 
			
		||||
    new AddrMapProt().fromBits(protBits)
 | 
			
		||||
    val protForRegion = sortedEntries.map { case (_, base, region) =>
 | 
			
		||||
      val inRegion = addr >= UInt(base) && addr < UInt(base + region.size)
 | 
			
		||||
      Mux(inRegion, UInt(region.attr.prot, AddrMapProt.SZ), UInt(0))
 | 
			
		||||
    }
 | 
			
		||||
    new AddrMapProt().fromBits(protForRegion.reduce(_|_))
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -502,53 +502,33 @@ class NastiRecursiveInterconnect(
 | 
			
		||||
    val nMasters: Int, val nSlaves: Int,
 | 
			
		||||
    addrmap: AddrMap, base: BigInt)
 | 
			
		||||
    (implicit p: Parameters) extends NastiInterconnect()(p) {
 | 
			
		||||
  var lastEnd = base
 | 
			
		||||
  var slaveInd = 0
 | 
			
		||||
  val levelSize = addrmap.size
 | 
			
		||||
 | 
			
		||||
  val realAddrMap = addrmap map { case AddrMapEntry(name, region) =>
 | 
			
		||||
    val start = lastEnd
 | 
			
		||||
    val size = region.size
 | 
			
		||||
 | 
			
		||||
    require(isPow2(size),
 | 
			
		||||
      s"Region $name size $size is not a power of 2")
 | 
			
		||||
    require(start % size == 0,
 | 
			
		||||
      f"Region $name start address 0x$start%x not divisible by 0x$size%x" )
 | 
			
		||||
    require(start >= lastEnd,
 | 
			
		||||
      f"Region $name start address 0x$start%x before previous region end")
 | 
			
		||||
 | 
			
		||||
    lastEnd = start + size
 | 
			
		||||
    (start, size)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  val addrHashMap = new AddrHashMap(addrmap, base)
 | 
			
		||||
  val routeSel = (addr: UInt) => {
 | 
			
		||||
    Vec(realAddrMap.map { case (start, size) =>
 | 
			
		||||
      addr >= UInt(start) && addr < UInt(start + size)
 | 
			
		||||
    }).toBits
 | 
			
		||||
    Cat(addrmap.map { case entry =>
 | 
			
		||||
      val hashEntry = addrHashMap(entry.name)
 | 
			
		||||
      addr >= UInt(hashEntry.start) && addr < UInt(hashEntry.start + hashEntry.region.size)
 | 
			
		||||
    }.reverse)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  val xbar = Module(new NastiCrossbar(nMasters, levelSize, routeSel))
 | 
			
		||||
  xbar.io.masters <> io.masters
 | 
			
		||||
 | 
			
		||||
  addrmap.zip(realAddrMap).zip(xbar.io.slaves).zipWithIndex.foreach {
 | 
			
		||||
    case (((entry, (start, size)), xbarSlave), i) => {
 | 
			
		||||
  io.slaves <> addrmap.zip(xbar.io.slaves).flatMap {
 | 
			
		||||
    case (entry, xbarSlave) => {
 | 
			
		||||
      entry.region match {
 | 
			
		||||
        case MemSize(_, _, _) =>
 | 
			
		||||
          io.slaves(slaveInd) <> xbarSlave
 | 
			
		||||
          slaveInd += 1
 | 
			
		||||
        case _: MemSize =>
 | 
			
		||||
          Some(xbarSlave)
 | 
			
		||||
        case MemSubmap(_, submap) if submap.isEmpty =>
 | 
			
		||||
          val err_slave = Module(new NastiErrorSlave)
 | 
			
		||||
          err_slave.io <> xbarSlave
 | 
			
		||||
          None
 | 
			
		||||
        case MemSubmap(_, submap) =>
 | 
			
		||||
          if (submap.isEmpty) {
 | 
			
		||||
            val err_slave = Module(new NastiErrorSlave)
 | 
			
		||||
            err_slave.io <> xbarSlave
 | 
			
		||||
          } else {
 | 
			
		||||
            val subSlaves = submap.countSlaves
 | 
			
		||||
            val outputs = io.slaves.drop(slaveInd).take(subSlaves)
 | 
			
		||||
            val ic = Module(new NastiRecursiveInterconnect(1, subSlaves, submap, start))
 | 
			
		||||
            ic.io.masters.head <> xbarSlave
 | 
			
		||||
            for ((o, s) <- outputs zip ic.io.slaves)
 | 
			
		||||
              o <> s
 | 
			
		||||
            slaveInd += subSlaves
 | 
			
		||||
          }
 | 
			
		||||
          val subSlaves = submap.countSlaves
 | 
			
		||||
          val ic = Module(new NastiRecursiveInterconnect(1, subSlaves, submap, addrHashMap(entry.name).start))
 | 
			
		||||
          ic.io.masters.head <> xbarSlave
 | 
			
		||||
          ic.io.slaves
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user