Merge AddrHashMap and AddrMap
This commit is contained in:
parent
695be2f0ae
commit
28161cab45
@ -16,7 +16,6 @@ case object PPNBits extends Field[Int]
|
|||||||
case object VPNBits extends Field[Int]
|
case object VPNBits extends Field[Int]
|
||||||
|
|
||||||
case object GlobalAddrMap extends Field[AddrMap]
|
case object GlobalAddrMap extends Field[AddrMap]
|
||||||
case object GlobalAddrHashMap extends Field[AddrHashMap]
|
|
||||||
|
|
||||||
trait HasAddrMapParameters {
|
trait HasAddrMapParameters {
|
||||||
implicit val p: Parameters
|
implicit val p: Parameters
|
||||||
@ -30,23 +29,27 @@ trait HasAddrMapParameters {
|
|||||||
val pgLevelBits = p(PgLevelBits)
|
val pgLevelBits = p(PgLevelBits)
|
||||||
val asIdBits = p(ASIdBits)
|
val asIdBits = p(ASIdBits)
|
||||||
|
|
||||||
val addrMap = p(GlobalAddrHashMap)
|
val addrMap = p(GlobalAddrMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
case class MemAttr(prot: Int, cacheable: Boolean = false)
|
case class MemAttr(prot: Int, cacheable: Boolean = false)
|
||||||
|
|
||||||
abstract class MemRegion {
|
sealed abstract class MemRegion {
|
||||||
def align: BigInt
|
def start: BigInt
|
||||||
def size: BigInt
|
def size: BigInt
|
||||||
def numSlaves: Int
|
def numSlaves: Int
|
||||||
|
def attr: MemAttr
|
||||||
|
|
||||||
|
def containsAddress(x: UInt) = UInt(start) <= x && x < UInt(start + size)
|
||||||
}
|
}
|
||||||
|
|
||||||
case class MemSize(size: BigInt, align: BigInt, attr: MemAttr) extends MemRegion {
|
case class MemSize(size: BigInt, attr: MemAttr) extends MemRegion {
|
||||||
|
def start = 0
|
||||||
def numSlaves = 1
|
def numSlaves = 1
|
||||||
}
|
}
|
||||||
case class MemSubmap(size: BigInt, entries: AddrMap) extends MemRegion {
|
|
||||||
val numSlaves = entries.countSlaves
|
case class MemRange(start: BigInt, size: BigInt, attr: MemAttr) extends MemRegion {
|
||||||
val align = entries.computeAlign
|
def numSlaves = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
object AddrMapProt {
|
object AddrMapProt {
|
||||||
@ -67,90 +70,80 @@ 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, 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
object AddrMap {
|
object AddrMap {
|
||||||
def apply(elems: AddrMapEntry*): AddrMap = new AddrMap(elems)
|
def apply(elems: AddrMapEntry*): AddrMap = new AddrMap(elems)
|
||||||
}
|
}
|
||||||
|
|
||||||
class AddrHashMap(addrmap: AddrMap, start: BigInt = BigInt(0)) {
|
class AddrMap(entriesIn: Seq[AddrMapEntry], val start: BigInt = BigInt(0)) extends MemRegion {
|
||||||
private val mapping = HashMap[String, AddrHashMapEntry]()
|
def isEmpty = entries.isEmpty
|
||||||
private val subMaps = HashMap[String, AddrHashMapEntry]()
|
def length = entries.size
|
||||||
|
def numSlaves = entries.map(_.region.numSlaves).foldLeft(0)(_ + _)
|
||||||
|
def attr = ???
|
||||||
|
|
||||||
private def genPairs(am: AddrMap, start: BigInt, startIdx: Int, prefix: String): (BigInt, Int) = {
|
private val slavePorts = HashMap[String, Int]()
|
||||||
var ind = startIdx
|
private val mapping = HashMap[String, MemRegion]()
|
||||||
|
|
||||||
|
val (size: BigInt, entries: Seq[AddrMapEntry]) = {
|
||||||
|
var ind = 0
|
||||||
var base = start
|
var base = start
|
||||||
am.foreach { ame =>
|
var rebasedEntries = collection.mutable.ArrayBuffer[AddrMapEntry]()
|
||||||
val name = prefix + ame.name
|
for (AddrMapEntry(name, r) <- entriesIn) {
|
||||||
base = (base + ame.region.align - 1) / ame.region.align * ame.region.align
|
if (r.start != 0) {
|
||||||
ame.region match {
|
val align = BigInt(1) << log2Ceil(r.size)
|
||||||
case r: MemSize =>
|
require(r.start >= base, s"region $name base address 0x${r.start.toString(16)} overlaps previous base 0x${base.toString(16)}")
|
||||||
mapping += name -> AddrHashMapEntry(ind, base, r)
|
require(r.start % align == 0, s"region $name base address 0x${r.start.toString(16)} not aligned to 0x${align.toString(16)}")
|
||||||
|
base = r.start
|
||||||
|
} else {
|
||||||
|
base = (base + r.size - 1) / r.size * r.size
|
||||||
|
}
|
||||||
|
|
||||||
|
r match {
|
||||||
|
case r: AddrMap =>
|
||||||
|
val subMap = new AddrMap(r.entries, base)
|
||||||
|
rebasedEntries += AddrMapEntry(name, subMap)
|
||||||
|
mapping += name -> subMap
|
||||||
|
mapping ++= subMap.mapping.map { case (k, v) => s"$name:$k" -> v }
|
||||||
|
slavePorts ++= subMap.slavePorts.map { case (k, v) => s"$name:$k" -> (ind + v) }
|
||||||
|
case _ =>
|
||||||
|
val e = MemRange(base, r.size, r.attr)
|
||||||
|
rebasedEntries += AddrMapEntry(name, e)
|
||||||
|
mapping += name -> e
|
||||||
|
slavePorts += name -> ind
|
||||||
|
}
|
||||||
|
|
||||||
|
ind += r.numSlaves
|
||||||
base += r.size
|
base += r.size
|
||||||
ind += 1
|
}
|
||||||
case r: MemSubmap =>
|
(base - start, rebasedEntries)
|
||||||
subMaps += name -> AddrHashMapEntry(-1, base, r)
|
|
||||||
ind = genPairs(r.entries, base, ind, name + ":")._2
|
|
||||||
base += r.size
|
|
||||||
}}
|
|
||||||
(base, ind)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val size = genPairs(addrmap, start, 0, "")._1
|
val flatten: Seq[(String, MemRange)] = {
|
||||||
|
val arr = new Array[(String, MemRange)](slavePorts.size)
|
||||||
val sortedEntries: Seq[(String, BigInt, MemSize)] = {
|
for ((name, port) <- slavePorts)
|
||||||
val arr = new Array[(String, BigInt, MemSize)](mapping.size)
|
arr(port) = (name, mapping(name).asInstanceOf[MemRange])
|
||||||
mapping.foreach { case (name, AddrHashMapEntry(port, base, region)) =>
|
arr
|
||||||
arr(port) = (name, base, region.asInstanceOf[MemSize])
|
|
||||||
}
|
|
||||||
arr.toSeq
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def nEntries: Int = mapping.size
|
def apply(name: String): MemRegion = mapping(name)
|
||||||
def apply(name: String): AddrHashMapEntry = mapping.getOrElse(name, subMaps(name))
|
def port(name: String): Int = slavePorts(name)
|
||||||
def subMap(name: String): (BigInt, AddrMap) = {
|
def subMap(name: String): AddrMap = mapping(name).asInstanceOf[AddrMap]
|
||||||
val m = subMaps(name)
|
def isInRegion(name: String, addr: UInt): Bool = mapping(name).containsAddress(addr)
|
||||||
(m.start, m.region.asInstanceOf[MemSubmap].entries)
|
|
||||||
}
|
|
||||||
|
|
||||||
def isInRegion(name: String, addr: UInt): Bool = {
|
|
||||||
val start = mapping(name).start
|
|
||||||
val size = mapping(name).region.size
|
|
||||||
UInt(start) <= addr && addr < UInt(start + size)
|
|
||||||
}
|
|
||||||
|
|
||||||
def isCacheable(addr: UInt): Bool = {
|
def isCacheable(addr: UInt): Bool = {
|
||||||
sortedEntries.filter(_._3.attr.cacheable).map { case (_, base, region) =>
|
flatten.filter(_._2.attr.cacheable).map { case (_, region) =>
|
||||||
UInt(base) <= addr && addr < UInt(base + region.size)
|
region.containsAddress(addr)
|
||||||
}.foldLeft(Bool(false))(_ || _)
|
}.foldLeft(Bool(false))(_ || _)
|
||||||
}
|
}
|
||||||
|
|
||||||
def isValid(addr: UInt): Bool = {
|
def isValid(addr: UInt): Bool = {
|
||||||
sortedEntries.map { case (_, base, region) =>
|
flatten.map { case (_, region) =>
|
||||||
addr >= UInt(base) && addr < UInt(base + region.size)
|
region.containsAddress(addr)
|
||||||
}.foldLeft(Bool(false))(_ || _)
|
}.foldLeft(Bool(false))(_ || _)
|
||||||
}
|
}
|
||||||
|
|
||||||
def getProt(addr: UInt): AddrMapProt = {
|
def getProt(addr: UInt): AddrMapProt = {
|
||||||
val protForRegion = sortedEntries.map { case (_, base, region) =>
|
val protForRegion = flatten.map { case (_, region) =>
|
||||||
val inRegion = addr >= UInt(base) && addr < UInt(base + region.size)
|
Mux(region.containsAddress(addr), UInt(region.attr.prot, AddrMapProt.SZ), UInt(0))
|
||||||
Mux(inRegion, UInt(region.attr.prot, AddrMapProt.SZ), UInt(0))
|
|
||||||
}
|
}
|
||||||
new AddrMapProt().fromBits(protForRegion.reduce(_|_))
|
new AddrMapProt().fromBits(protForRegion.reduce(_|_))
|
||||||
}
|
}
|
||||||
|
@ -506,37 +506,29 @@ abstract class NastiInterconnect(implicit p: Parameters) extends NastiModule()(p
|
|||||||
lazy val io = new NastiInterconnectIO(nMasters, nSlaves)
|
lazy val io = new NastiInterconnectIO(nMasters, nSlaves)
|
||||||
}
|
}
|
||||||
|
|
||||||
class NastiRecursiveInterconnect(
|
class NastiRecursiveInterconnect(val nMasters: Int, addrMap: AddrMap)
|
||||||
val nMasters: Int, val nSlaves: Int,
|
|
||||||
addrmap: AddrMap, base: BigInt)
|
|
||||||
(implicit p: Parameters) extends NastiInterconnect()(p) {
|
(implicit p: Parameters) extends NastiInterconnect()(p) {
|
||||||
val levelSize = addrmap.size
|
def port(name: String) = io.slaves(addrMap.port(name))
|
||||||
|
val nSlaves = addrMap.numSlaves
|
||||||
|
val routeSel = (addr: UInt) =>
|
||||||
|
Cat(addrMap.entries.map(e => addrMap(e.name).containsAddress(addr)).reverse)
|
||||||
|
|
||||||
val addrHashMap = new AddrHashMap(addrmap, base)
|
val xbar = Module(new NastiCrossbar(nMasters, addrMap.length, routeSel))
|
||||||
val routeSel = (addr: UInt) => {
|
|
||||||
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
|
xbar.io.masters <> io.masters
|
||||||
|
|
||||||
io.slaves <> addrmap.zip(xbar.io.slaves).flatMap {
|
io.slaves <> addrMap.entries.zip(xbar.io.slaves).flatMap {
|
||||||
case (entry, xbarSlave) => {
|
case (entry, xbarSlave) => {
|
||||||
entry.region match {
|
entry.region match {
|
||||||
case _: MemSize =>
|
case submap: AddrMap if submap.entries.isEmpty =>
|
||||||
Some(xbarSlave)
|
|
||||||
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
|
||||||
None
|
None
|
||||||
case MemSubmap(_, submap) =>
|
case submap: AddrMap =>
|
||||||
val subSlaves = submap.countSlaves
|
val ic = Module(new NastiRecursiveInterconnect(1, submap))
|
||||||
val ic = Module(new NastiRecursiveInterconnect(1, subSlaves, submap, addrHashMap(entry.name).start))
|
|
||||||
ic.io.masters.head <> xbarSlave
|
ic.io.masters.head <> xbarSlave
|
||||||
ic.io.slaves
|
ic.io.slaves
|
||||||
|
case r: MemRange =>
|
||||||
|
Some(xbarSlave)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user