Address Map refactoring
This commit is contained in:
parent
c8b1f0801b
commit
e4ace55d77
@ -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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 =>
|
||||||
case MemSubmap(_, submap) =>
|
|
||||||
if (submap.isEmpty) {
|
|
||||||
val err_slave = Module(new NastiErrorSlave)
|
val err_slave = Module(new NastiErrorSlave)
|
||||||
err_slave.io <> xbarSlave
|
err_slave.io <> xbarSlave
|
||||||
} else {
|
None
|
||||||
|
case MemSubmap(_, submap) =>
|
||||||
val subSlaves = submap.countSlaves
|
val subSlaves = submap.countSlaves
|
||||||
val outputs = io.slaves.drop(slaveInd).take(subSlaves)
|
val ic = Module(new NastiRecursiveInterconnect(1, subSlaves, submap, addrHashMap(entry.name).start))
|
||||||
val ic = Module(new NastiRecursiveInterconnect(1, subSlaves, submap, start))
|
|
||||||
ic.io.masters.head <> xbarSlave
|
ic.io.masters.head <> xbarSlave
|
||||||
for ((o, s) <- outputs zip ic.io.slaves)
|
ic.io.slaves
|
||||||
o <> s
|
|
||||||
slaveInd += subSlaves
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user