1
0

Address Map refactoring

This commit is contained in:
Andrew Waterman 2016-04-28 16:08:32 -07:00
parent c8b1f0801b
commit e4ace55d77
2 changed files with 72 additions and 81 deletions

View File

@ -32,25 +32,30 @@ trait HasAddrMapParameters {
val addrMap = new AddrHashMap(p(GlobalAddrMap)) val addrMap = new AddrHashMap(p(GlobalAddrMap))
} }
case class MemAttr(prot: Int, cacheable: Boolean = false)
abstract class MemRegion { abstract class MemRegion {
def align: BigInt
def size: BigInt def size: BigInt
def numSlaves: Int 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 def numSlaves = 1
} }
case class MemSubmap(size: BigInt, entries: AddrMap) extends MemRegion { case class MemSubmap(size: BigInt, entries: AddrMap) extends MemRegion {
val numSlaves = entries.countSlaves val numSlaves = entries.countSlaves
val align = entries.computeAlign
} }
object AddrMapConsts { object AddrMapProt {
val R = 0x1 val R = 0x1
val W = 0x2 val W = 0x2
val X = 0x4 val X = 0x4
val RW = R | W val RW = R | W
val RX = R | X val RX = R | X
val RWX = R | W | X val RWX = R | W | X
val SZ = 3
} }
class AddrMapProt extends Bundle { class AddrMapProt extends Bundle {
@ -61,15 +66,21 @@ class AddrMapProt extends Bundle {
case class AddrMapEntry(name: String, region: MemRegion) 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] { 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 apply(index: Int): AddrMapEntry = entries(index)
def length: Int = entries.size def length: Int = entries.size
def countSlaves: Int = entries.map(_.region.numSlaves).foldLeft(0)(_ + _) 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) override def tail: AddrMap = new AddrMap(entries.tail)
} }
@ -78,68 +89,68 @@ object AddrMap {
} }
class AddrHashMap(addrmap: AddrMap, start: BigInt = BigInt(0)) { 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)] = { private def genPairs(am: AddrMap, start: BigInt, startIdx: Int, prefix: String): (BigInt, Int) = {
var ind = 0 var ind = startIdx
var base = start var base = start
var pairs = Seq[(String, AddrHashMapEntry)]() am.foreach { ame =>
am.foreach { val name = prefix + ame.name
case AddrMapEntry(name, MemSize(size, prot, cacheable)) => base = (base + ame.region.align - 1) / ame.region.align * ame.region.align
pairs = (name, AddrHashMapEntry(ind, base, size, prot, cacheable)) +: pairs ame.region match {
base += size case r: MemSize =>
mapping += name -> AddrHashMapEntry(ind, base, r)
base += r.size
ind += 1 ind += 1
case AddrMapEntry(name, MemSubmap(size, submap)) => case r: MemSubmap =>
val subpairs = genPairs(submap, base).map { subMaps += name -> AddrHashMapEntry(-1, base, r)
case (subname, AddrHashMapEntry(subind, subbase, subsize, prot, cacheable)) => ind = genPairs(r.entries, base, ind, name + ":")._2
(name + ":" + subname, base += r.size
AddrHashMapEntry(ind + subind, subbase, subsize, prot, cacheable)) }}
} (base, ind)
pairs = subpairs ++ pairs
ind += subpairs.size
base += size
}
pairs
} }
for ((name, ind) <- genPairs(addrmap, start)) { mapping(name) = ind } val size = genPairs(addrmap, start, 0, "")._1
def nEntries: Int = mapping.size val sortedEntries: Seq[(String, BigInt, MemSize)] = {
def apply(name: String): AddrHashMapEntry = mapping(name) val arr = new Array[(String, BigInt, MemSize)](mapping.size)
def get(name: String): Option[AddrHashMapEntry] = mapping.get(name) mapping.foreach { case (name, AddrHashMapEntry(port, base, region)) =>
def sortedEntries(): Seq[(String, BigInt, BigInt, Int, Boolean)] = { arr(port) = (name, base, region.asInstanceOf[MemSize])
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)
} }
arr.toSeq 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 = { def isInRegion(name: String, addr: UInt): Bool = {
val start = mapping(name).start val start = mapping(name).start
val size = mapping(name).size val size = mapping(name).region.size
UInt(start) <= addr && addr < UInt(start + size) UInt(start) <= addr && addr < UInt(start + size)
} }
def isCacheable(addr: UInt): Bool = { def isCacheable(addr: UInt): Bool = {
sortedEntries().map { case (_, base, size, _, cacheable) => sortedEntries.filter(_._3.attr.cacheable).map { case (_, base, region) =>
UInt(base) <= addr && addr < UInt(base + size) && Bool(cacheable) UInt(base) <= addr && addr < UInt(base + region.size)
}.reduce(_ || _) }.foldLeft(Bool(false))(_ || _)
} }
def isValid(addr: UInt): Bool = { def isValid(addr: UInt): Bool = {
addr < UInt(start) || sortedEntries().map { sortedEntries.map { case (_, base, region) =>
case (_, base, size, _, _) => addr >= UInt(base) && addr < UInt(base + region.size)
addr >= UInt(base) && addr < UInt(base + size) }.foldLeft(Bool(false))(_ || _)
}.reduceLeft(_ || _)
} }
def getProt(addr: UInt): AddrMapProt = { def getProt(addr: UInt): AddrMapProt = {
val protBits = Mux(addr < UInt(start), val protForRegion = sortedEntries.map { case (_, base, region) =>
Bits(AddrMapConsts.RWX, 3), val inRegion = addr >= UInt(base) && addr < UInt(base + region.size)
Mux1H(sortedEntries().map { case (_, base, size, prot, _) => Mux(inRegion, UInt(region.attr.prot, AddrMapProt.SZ), UInt(0))
(addr >= UInt(base) && addr < UInt(base + size), Bits(prot, 3)) }
})) new AddrMapProt().fromBits(protForRegion.reduce(_|_))
new AddrMapProt().fromBits(protBits)
} }
} }

View File

@ -502,53 +502,33 @@ class NastiRecursiveInterconnect(
val nMasters: Int, val nSlaves: Int, val nMasters: Int, val nSlaves: Int,
addrmap: AddrMap, base: BigInt) addrmap: AddrMap, base: BigInt)
(implicit p: Parameters) extends NastiInterconnect()(p) { (implicit p: Parameters) extends NastiInterconnect()(p) {
var lastEnd = base
var slaveInd = 0
val levelSize = addrmap.size val levelSize = addrmap.size
val realAddrMap = addrmap map { case AddrMapEntry(name, region) => val addrHashMap = new AddrHashMap(addrmap, base)
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 routeSel = (addr: UInt) => { val routeSel = (addr: UInt) => {
Vec(realAddrMap.map { case (start, size) => Cat(addrmap.map { case entry =>
addr >= UInt(start) && addr < UInt(start + size) val hashEntry = addrHashMap(entry.name)
}).toBits addr >= UInt(hashEntry.start) && addr < UInt(hashEntry.start + hashEntry.region.size)
}.reverse)
} }
val xbar = Module(new NastiCrossbar(nMasters, levelSize, routeSel)) val xbar = Module(new NastiCrossbar(nMasters, levelSize, routeSel))
xbar.io.masters <> io.masters xbar.io.masters <> io.masters
addrmap.zip(realAddrMap).zip(xbar.io.slaves).zipWithIndex.foreach { io.slaves <> addrmap.zip(xbar.io.slaves).flatMap {
case (((entry, (start, size)), xbarSlave), i) => { case (entry, xbarSlave) => {
entry.region match { entry.region match {
case MemSize(_, _, _) => case _: MemSize =>
io.slaves(slaveInd) <> xbarSlave Some(xbarSlave)
slaveInd += 1 case MemSubmap(_, submap) if submap.isEmpty =>
val err_slave = Module(new NastiErrorSlave)
err_slave.io <> xbarSlave
None
case MemSubmap(_, submap) => case MemSubmap(_, submap) =>
if (submap.isEmpty) { val subSlaves = submap.countSlaves
val err_slave = Module(new NastiErrorSlave) val ic = Module(new NastiRecursiveInterconnect(1, subSlaves, submap, addrHashMap(entry.name).start))
err_slave.io <> xbarSlave ic.io.masters.head <> xbarSlave
} else { ic.io.slaves
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
}
} }
} }
} }