1
0
rocket-chip/junctions/src/main/scala/addrmap.scala

154 lines
4.3 KiB
Scala
Raw Normal View History

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]
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-06-03 22:46:53 +02:00
val addrMap = p(GlobalAddrMap)
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-06-03 22:46:53 +02:00
sealed abstract class MemRegion {
def start: BigInt
def size: BigInt
def numSlaves: Int
2016-06-03 22:46:53 +02:00
def attr: MemAttr
def containsAddress(x: UInt) = UInt(start) <= x && x < UInt(start + size)
}
2015-10-06 05:33:55 +02:00
2016-06-03 22:46:53 +02:00
case class MemSize(size: BigInt, attr: MemAttr) extends MemRegion {
def start = 0
def numSlaves = 1
}
2016-06-03 22:46:53 +02:00
case class MemRange(start: BigInt, size: BigInt, attr: MemAttr) extends MemRegion {
def numSlaves = 1
}
2015-10-06 05:33:55 +02:00
2016-04-29 01:08:32 +02:00
object AddrMapProt {
val R = 0x1
2015-10-06 05:33:55 +02:00
val W = 0x2
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()
val w = Bool()
val r = Bool()
2015-10-06 05:33:55 +02:00
}
case class AddrMapEntry(name: String, region: MemRegion)
2015-10-06 05:33:55 +02:00
object AddrMap {
def apply(elems: AddrMapEntry*): AddrMap = new AddrMap(elems)
}
2016-06-03 22:46:53 +02:00
class AddrMap(entriesIn: Seq[AddrMapEntry], val start: BigInt = BigInt(0)) extends MemRegion {
private val slavePorts = HashMap[String, Int]()
private val mapping = HashMap[String, MemRegion]()
2015-10-06 05:33:55 +02:00
2016-08-10 07:14:32 +02:00
def isEmpty = entries.isEmpty
def length = entries.size
def numSlaves = slavePorts.size
2016-08-10 06:20:54 +02:00
val (size: BigInt, entries: Seq[AddrMapEntry], attr: MemAttr) = {
2016-06-03 22:46:53 +02:00
var ind = 0
var base = start
var rebasedEntries = collection.mutable.ArrayBuffer[AddrMapEntry]()
2016-08-10 06:20:54 +02:00
var prot = 0
var cacheable = true
2016-06-03 22:46:53 +02:00
for (AddrMapEntry(name, r) <- entriesIn) {
if (r.start != 0) {
val align = BigInt(1) << log2Ceil(r.size)
require(r.start >= base, s"region $name base address 0x${r.start.toString(16)} overlaps previous base 0x${base.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
2016-08-10 06:20:54 +02:00
prot |= r.attr.prot
cacheable &&= r.attr.cacheable
2015-10-06 05:33:55 +02:00
}
2016-08-10 06:20:54 +02:00
(base - start, rebasedEntries, MemAttr(prot, cacheable))
2015-10-06 05:33:55 +02:00
}
2016-08-10 07:14:32 +02:00
val flatten: Seq[AddrMapEntry] = {
mapping.toSeq.map {
case (name, range: MemRange) => Some(AddrMapEntry(name, range))
case _ => None
}.flatten.sortBy(_.region.start)
2016-04-29 01:08:32 +02:00
}
2016-08-10 06:20:54 +02:00
def toRange: MemRange = MemRange(start, size, attr)
2016-06-03 22:46:53 +02:00
def apply(name: String): MemRegion = mapping(name)
def contains(name: String): Boolean = mapping.contains(name)
2016-06-03 22:46:53 +02:00
def port(name: String): Int = slavePorts(name)
def subMap(name: String): AddrMap = mapping(name).asInstanceOf[AddrMap]
def isInRegion(name: String, addr: UInt): Bool = mapping(name).containsAddress(addr)
def isCacheable(addr: UInt): Bool = {
2016-08-10 07:14:32 +02:00
flatten.filter(_.region.attr.cacheable).map(
_.region.containsAddress(addr)
).foldLeft(Bool(false))(_ || _)
}
2015-10-06 05:33:55 +02:00
def isValid(addr: UInt): Bool = {
2016-08-10 07:14:32 +02:00
flatten.map(_.region.containsAddress(addr)).foldLeft(Bool(false))(_ || _)
2015-10-06 05:33:55 +02:00
}
def getProt(addr: UInt): AddrMapProt = {
2016-08-10 07:14:32 +02:00
val protForRegion = flatten.map { entry =>
Mux(entry.region.containsAddress(addr),
UInt(entry.region.attr.prot, AddrMapProt.SZ), UInt(0))
2016-04-29 01:08:32 +02:00
}
new AddrMapProt().fromBits(protForRegion.reduce(_|_))
2015-10-06 05:33:55 +02:00
}
}