diff --git a/junctions/src/main/scala/addrmap.scala b/junctions/src/main/scala/addrmap.scala index 64cf293e..d5ddeb95 100644 --- a/junctions/src/main/scala/addrmap.scala +++ b/junctions/src/main/scala/addrmap.scala @@ -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(_|_)) } } diff --git a/junctions/src/main/scala/nasti.scala b/junctions/src/main/scala/nasti.scala index cbee05b2..e9324bd3 100644 --- a/junctions/src/main/scala/nasti.scala +++ b/junctions/src/main/scala/nasti.scala @@ -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 } } }