2015-10-06 05:33:55 +02:00
|
|
|
// See LICENSE for license details.
|
|
|
|
|
|
|
|
package junctions
|
|
|
|
|
|
|
|
import Chisel._
|
2015-10-22 03:15:46 +02:00
|
|
|
import cde.{Parameters, Field}
|
2015-10-06 05:33:55 +02:00
|
|
|
import scala.collection.mutable.HashMap
|
|
|
|
|
2015-10-07 03:14:51 +02:00
|
|
|
case object PAddrBits extends Field[Int]
|
|
|
|
case object VAddrBits extends Field[Int]
|
|
|
|
case object PgIdxBits extends Field[Int]
|
|
|
|
case object PgLevels extends Field[Int]
|
|
|
|
case object PgLevelBits extends Field[Int]
|
|
|
|
case object ASIdBits extends Field[Int]
|
|
|
|
case object PPNBits extends Field[Int]
|
|
|
|
case object VPNBits extends Field[Int]
|
|
|
|
|
|
|
|
case object GlobalAddrMap extends Field[AddrMap]
|
2016-05-03 03:22:43 +02:00
|
|
|
case object GlobalAddrHashMap extends Field[AddrHashMap]
|
2015-10-07 03:14:51 +02:00
|
|
|
|
|
|
|
trait HasAddrMapParameters {
|
|
|
|
implicit val p: Parameters
|
|
|
|
|
|
|
|
val paddrBits = p(PAddrBits)
|
|
|
|
val vaddrBits = p(VAddrBits)
|
|
|
|
val pgIdxBits = p(PgIdxBits)
|
|
|
|
val ppnBits = p(PPNBits)
|
|
|
|
val vpnBits = p(VPNBits)
|
|
|
|
val pgLevels = p(PgLevels)
|
|
|
|
val pgLevelBits = p(PgLevelBits)
|
|
|
|
val asIdBits = p(ASIdBits)
|
|
|
|
|
2016-05-03 03:22:43 +02:00
|
|
|
val addrMap = p(GlobalAddrHashMap)
|
2015-10-07 03:14:51 +02:00
|
|
|
}
|
|
|
|
|
2016-04-29 01:08:32 +02:00
|
|
|
case class MemAttr(prot: Int, cacheable: Boolean = false)
|
|
|
|
|
2016-04-27 23:51:52 +02:00
|
|
|
abstract class MemRegion {
|
2016-04-29 01:08:32 +02:00
|
|
|
def align: BigInt
|
2016-04-27 23:51:52 +02:00
|
|
|
def size: BigInt
|
|
|
|
def numSlaves: Int
|
|
|
|
}
|
2015-10-06 05:33:55 +02:00
|
|
|
|
2016-04-29 01:08:32 +02:00
|
|
|
case class MemSize(size: BigInt, align: BigInt, attr: MemAttr) extends MemRegion {
|
2016-04-27 23:51:52 +02:00
|
|
|
def numSlaves = 1
|
|
|
|
}
|
|
|
|
case class MemSubmap(size: BigInt, entries: AddrMap) extends MemRegion {
|
|
|
|
val numSlaves = entries.countSlaves
|
2016-04-29 01:08:32 +02:00
|
|
|
val align = entries.computeAlign
|
2016-04-27 23:51:52 +02:00
|
|
|
}
|
2015-10-06 05:33:55 +02:00
|
|
|
|
2016-04-29 01:08:32 +02:00
|
|
|
object AddrMapProt {
|
2015-12-05 09:26:16 +01:00
|
|
|
val R = 0x1
|
2015-10-06 05:33:55 +02:00
|
|
|
val W = 0x2
|
2015-12-05 09:26:16 +01:00
|
|
|
val X = 0x4
|
2015-10-06 05:33:55 +02:00
|
|
|
val RW = R | W
|
|
|
|
val RX = R | X
|
|
|
|
val RWX = R | W | X
|
2016-04-29 01:08:32 +02:00
|
|
|
val SZ = 3
|
2015-10-06 05:33:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
class AddrMapProt extends Bundle {
|
|
|
|
val x = Bool()
|
2015-12-05 09:26:16 +01:00
|
|
|
val w = Bool()
|
|
|
|
val r = Bool()
|
2015-10-06 05:33:55 +02:00
|
|
|
}
|
|
|
|
|
2016-04-27 23:52:05 +02:00
|
|
|
case class AddrMapEntry(name: String, region: MemRegion)
|
2015-10-06 05:33:55 +02:00
|
|
|
|
2016-04-29 01:08:32 +02:00
|
|
|
case class AddrHashMapEntry(port: Int, start: BigInt, region: MemRegion)
|
2015-10-06 05:33:55 +02:00
|
|
|
|
|
|
|
class AddrMap(entries: Seq[AddrMapEntry]) extends scala.collection.IndexedSeq[AddrMapEntry] {
|
2016-04-29 01:08:32 +02:00
|
|
|
private val hash = HashMap(entries.map(e => (e.name, e.region)):_*)
|
|
|
|
|
2015-10-06 05:33:55 +02:00
|
|
|
def apply(index: Int): AddrMapEntry = entries(index)
|
|
|
|
|
|
|
|
def length: Int = entries.size
|
|
|
|
|
2016-04-27 23:51:52 +02:00
|
|
|
def countSlaves: Int = entries.map(_.region.numSlaves).foldLeft(0)(_ + _)
|
2016-04-22 00:33:53 +02:00
|
|
|
|
2016-04-29 01:08:32 +02:00
|
|
|
def computeSize: BigInt = new AddrHashMap(this).size
|
|
|
|
|
|
|
|
def computeAlign: BigInt = entries.map(_.region.align).foldLeft(BigInt(1))(_ max _)
|
|
|
|
|
2016-04-22 00:33:53 +02:00
|
|
|
override def tail: AddrMap = new AddrMap(entries.tail)
|
2015-10-06 05:33:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
object AddrMap {
|
|
|
|
def apply(elems: AddrMapEntry*): AddrMap = new AddrMap(elems)
|
|
|
|
}
|
|
|
|
|
2016-04-22 00:33:53 +02:00
|
|
|
class AddrHashMap(addrmap: AddrMap, start: BigInt = BigInt(0)) {
|
2016-04-29 01:08:32 +02:00
|
|
|
private val mapping = HashMap[String, AddrHashMapEntry]()
|
|
|
|
private val subMaps = HashMap[String, AddrHashMapEntry]()
|
2015-10-06 05:33:55 +02:00
|
|
|
|
2016-04-29 01:08:32 +02:00
|
|
|
private def genPairs(am: AddrMap, start: BigInt, startIdx: Int, prefix: String): (BigInt, Int) = {
|
|
|
|
var ind = startIdx
|
2016-01-15 01:41:32 +01:00
|
|
|
var base = start
|
2016-04-29 01:08:32 +02:00
|
|
|
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
|
2016-04-27 23:52:05 +02:00
|
|
|
ind += 1
|
2016-04-29 01:08:32 +02:00
|
|
|
case r: MemSubmap =>
|
|
|
|
subMaps += name -> AddrHashMapEntry(-1, base, r)
|
|
|
|
ind = genPairs(r.entries, base, ind, name + ":")._2
|
|
|
|
base += r.size
|
|
|
|
}}
|
|
|
|
(base, ind)
|
2015-10-06 05:33:55 +02:00
|
|
|
}
|
|
|
|
|
2016-04-29 01:08:32 +02:00
|
|
|
val size = genPairs(addrmap, start, 0, "")._1
|
2015-10-06 05:33:55 +02:00
|
|
|
|
2016-04-29 01:08:32 +02:00
|
|
|
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])
|
2015-10-06 05:33:55 +02:00
|
|
|
}
|
|
|
|
arr.toSeq
|
|
|
|
}
|
|
|
|
|
2016-04-29 01:08:32 +02:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2016-04-22 00:33:53 +02:00
|
|
|
def isInRegion(name: String, addr: UInt): Bool = {
|
|
|
|
val start = mapping(name).start
|
2016-04-29 01:08:32 +02:00
|
|
|
val size = mapping(name).region.size
|
2016-04-22 00:33:53 +02:00
|
|
|
UInt(start) <= addr && addr < UInt(start + size)
|
|
|
|
}
|
|
|
|
|
|
|
|
def isCacheable(addr: UInt): Bool = {
|
2016-04-29 01:08:32 +02:00
|
|
|
sortedEntries.filter(_._3.attr.cacheable).map { case (_, base, region) =>
|
|
|
|
UInt(base) <= addr && addr < UInt(base + region.size)
|
|
|
|
}.foldLeft(Bool(false))(_ || _)
|
2016-04-22 00:33:53 +02:00
|
|
|
}
|
|
|
|
|
2015-10-06 05:33:55 +02:00
|
|
|
def isValid(addr: UInt): Bool = {
|
2016-04-29 01:08:32 +02:00
|
|
|
sortedEntries.map { case (_, base, region) =>
|
|
|
|
addr >= UInt(base) && addr < UInt(base + region.size)
|
|
|
|
}.foldLeft(Bool(false))(_ || _)
|
2015-10-06 05:33:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
def getProt(addr: UInt): AddrMapProt = {
|
2016-04-29 01:08:32 +02:00
|
|
|
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(_|_))
|
2015-10-06 05:33:55 +02:00
|
|
|
}
|
|
|
|
}
|