factor out common cache subcomponents into uncore.util
This commit is contained in:
parent
16d0f522b0
commit
dae6772624
@ -11,6 +11,7 @@ import uncore.coherence._
|
|||||||
import uncore.agents._
|
import uncore.agents._
|
||||||
import uncore.devices._
|
import uncore.devices._
|
||||||
import uncore.converters._
|
import uncore.converters._
|
||||||
|
import uncore.util._
|
||||||
import rocket._
|
import rocket._
|
||||||
import util._
|
import util._
|
||||||
import util.ConfigUtils._
|
import util.ConfigUtils._
|
||||||
|
@ -3,7 +3,7 @@ package groundtest
|
|||||||
import Chisel._
|
import Chisel._
|
||||||
import uncore.tilelink._
|
import uncore.tilelink._
|
||||||
import uncore.constants._
|
import uncore.constants._
|
||||||
import uncore.agents._
|
import uncore.util._
|
||||||
import util._
|
import util._
|
||||||
import config._
|
import config._
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import diplomacy._
|
|||||||
import uncore.tilelink._
|
import uncore.tilelink._
|
||||||
import uncore.coherence._
|
import uncore.coherence._
|
||||||
import uncore.agents._
|
import uncore.agents._
|
||||||
|
import uncore.util._
|
||||||
import uncore.devices.NTiles
|
import uncore.devices.NTiles
|
||||||
import junctions._
|
import junctions._
|
||||||
import config._
|
import config._
|
||||||
|
@ -3,7 +3,7 @@ package groundtest
|
|||||||
import Chisel._
|
import Chisel._
|
||||||
import uncore.tilelink._
|
import uncore.tilelink._
|
||||||
import uncore.constants._
|
import uncore.constants._
|
||||||
import uncore.agents._
|
import uncore.util._
|
||||||
import util._
|
import util._
|
||||||
import rocket._
|
import rocket._
|
||||||
import rocketchip._
|
import rocketchip._
|
||||||
|
@ -3,7 +3,7 @@ package groundtest
|
|||||||
import Chisel._
|
import Chisel._
|
||||||
import rocket._
|
import rocket._
|
||||||
import uncore.tilelink._
|
import uncore.tilelink._
|
||||||
import uncore.agents.CacheName
|
import uncore.util.CacheName
|
||||||
import uncore.tilelink2._
|
import uncore.tilelink2._
|
||||||
import rocketchip.ExtMem
|
import rocketchip.ExtMem
|
||||||
import diplomacy._
|
import diplomacy._
|
||||||
|
@ -5,7 +5,6 @@ package rocket
|
|||||||
import Chisel._
|
import Chisel._
|
||||||
import Chisel.ImplicitConversions._
|
import Chisel.ImplicitConversions._
|
||||||
import diplomacy._
|
import diplomacy._
|
||||||
import uncore.agents._
|
|
||||||
import uncore.constants._
|
import uncore.constants._
|
||||||
import uncore.tilelink2._
|
import uncore.tilelink2._
|
||||||
import uncore.util._
|
import uncore.util._
|
||||||
|
@ -6,7 +6,7 @@ import Chisel._
|
|||||||
import config.{Parameters, Field}
|
import config.{Parameters, Field}
|
||||||
import diplomacy._
|
import diplomacy._
|
||||||
import uncore.tilelink2._
|
import uncore.tilelink2._
|
||||||
import uncore.agents._
|
import uncore.util._
|
||||||
import uncore.constants._
|
import uncore.constants._
|
||||||
import uncore.tilelink.{TLKey, TLId}
|
import uncore.tilelink.{TLKey, TLId}
|
||||||
import util.ParameterizedBundle
|
import util.ParameterizedBundle
|
||||||
|
@ -5,7 +5,6 @@ package rocket
|
|||||||
import Chisel._
|
import Chisel._
|
||||||
import Chisel.ImplicitConversions._
|
import Chisel.ImplicitConversions._
|
||||||
import diplomacy._
|
import diplomacy._
|
||||||
import uncore.agents._
|
|
||||||
import uncore.constants._
|
import uncore.constants._
|
||||||
import uncore.tilelink._
|
import uncore.tilelink._
|
||||||
import uncore.tilelink2._
|
import uncore.tilelink2._
|
||||||
|
@ -6,7 +6,7 @@ import Chisel._
|
|||||||
import config._
|
import config._
|
||||||
import util._
|
import util._
|
||||||
import Chisel.ImplicitConversions._
|
import Chisel.ImplicitConversions._
|
||||||
import uncore.agents.PseudoLRU
|
import uncore.util.PseudoLRU
|
||||||
|
|
||||||
case object BtbKey extends Field[BtbParameters]
|
case object BtbKey extends Field[BtbParameters]
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
package rocket
|
package rocket
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import uncore.agents._
|
import uncore.util.PseudoLRU
|
||||||
import uncore.constants._
|
import uncore.constants._
|
||||||
import util._
|
import util._
|
||||||
import Chisel.ImplicitConversions._
|
import Chisel.ImplicitConversions._
|
||||||
|
@ -5,7 +5,7 @@ package rocket
|
|||||||
import Chisel._
|
import Chisel._
|
||||||
import uncore.tilelink._
|
import uncore.tilelink._
|
||||||
import uncore.constants._
|
import uncore.constants._
|
||||||
import uncore.agents.CacheName
|
import uncore.util.CacheName
|
||||||
import util._
|
import util._
|
||||||
import Chisel.ImplicitConversions._
|
import Chisel.ImplicitConversions._
|
||||||
import config._
|
import config._
|
||||||
|
@ -4,7 +4,7 @@ package rocket
|
|||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import uncore.devices._
|
import uncore.devices._
|
||||||
import uncore.agents.CacheName
|
import uncore.util.CacheName
|
||||||
import uncore.constants._
|
import uncore.constants._
|
||||||
import uncore.tilelink2._
|
import uncore.tilelink2._
|
||||||
import util._
|
import util._
|
||||||
|
@ -6,7 +6,7 @@ import Chisel._
|
|||||||
import diplomacy._
|
import diplomacy._
|
||||||
import uncore.tilelink._
|
import uncore.tilelink._
|
||||||
import uncore.tilelink2._
|
import uncore.tilelink2._
|
||||||
import uncore.agents._
|
import uncore.util.{CacheName, CacheBlockBytes}
|
||||||
import uncore.converters._
|
import uncore.converters._
|
||||||
import uncore.devices._
|
import uncore.devices._
|
||||||
import util._
|
import util._
|
||||||
|
@ -8,8 +8,7 @@ import Chisel.ImplicitConversions._
|
|||||||
import scala.math._
|
import scala.math._
|
||||||
import config._
|
import config._
|
||||||
import diplomacy._
|
import diplomacy._
|
||||||
import uncore.agents._
|
import uncore.util._
|
||||||
import uncore.coherence._
|
|
||||||
import uncore.tilelink2._
|
import uncore.tilelink2._
|
||||||
|
|
||||||
case object PgLevels extends Field[Int]
|
case object PgLevels extends Field[Int]
|
||||||
|
@ -5,186 +5,14 @@ package uncore.agents
|
|||||||
import Chisel._
|
import Chisel._
|
||||||
import scala.reflect.ClassTag
|
import scala.reflect.ClassTag
|
||||||
import junctions.PAddrBits
|
import junctions.PAddrBits
|
||||||
import util.ParameterizedBundle
|
|
||||||
import uncore.util.AMOALU
|
|
||||||
import uncore.coherence._
|
import uncore.coherence._
|
||||||
import uncore.tilelink._
|
import uncore.tilelink._
|
||||||
import uncore.constants._
|
import uncore.constants._
|
||||||
import uncore.util._
|
import uncore.util._
|
||||||
import util._
|
import util._
|
||||||
import config._
|
import config.{Parameters, Field}
|
||||||
|
|
||||||
case class CacheConfig(
|
|
||||||
nSets: Int,
|
|
||||||
nWays: Int,
|
|
||||||
rowBits: Int,
|
|
||||||
nTLBEntries: Int,
|
|
||||||
cacheIdBits: Int,
|
|
||||||
splitMetadata: Boolean)
|
|
||||||
case class CacheName(id: String) extends Field[CacheConfig]
|
|
||||||
case object CacheName extends Field[CacheName]
|
|
||||||
|
|
||||||
case object Replacer extends Field[() => ReplacementPolicy]
|
|
||||||
case object L2Replacer extends Field[() => SeqReplacementPolicy]
|
|
||||||
case object NPrimaryMisses extends Field[Int]
|
|
||||||
case object NSecondaryMisses extends Field[Int]
|
|
||||||
case object CacheBlockBytes extends Field[Int]
|
|
||||||
case object ECCCode extends Field[Option[Code]]
|
|
||||||
case object CacheId extends Field[Int]
|
case object CacheId extends Field[Int]
|
||||||
|
|
||||||
trait HasCacheParameters {
|
|
||||||
implicit val p: Parameters
|
|
||||||
val cacheConfig = p(p(CacheName))
|
|
||||||
val nSets = cacheConfig.nSets
|
|
||||||
val blockOffBits = p(CacheBlockOffsetBits)
|
|
||||||
val cacheIdBits = cacheConfig.cacheIdBits
|
|
||||||
val idxBits = log2Up(cacheConfig.nSets)
|
|
||||||
val untagBits = blockOffBits + cacheIdBits + idxBits
|
|
||||||
val tagBits = p(PAddrBits) - untagBits
|
|
||||||
val nWays = cacheConfig.nWays
|
|
||||||
val wayBits = log2Up(nWays)
|
|
||||||
val isDM = nWays == 1
|
|
||||||
val rowBits = cacheConfig.rowBits
|
|
||||||
val rowBytes = rowBits/8
|
|
||||||
val rowOffBits = log2Up(rowBytes)
|
|
||||||
val code = p(ECCCode).getOrElse(new IdentityCode)
|
|
||||||
val hasSplitMetadata = cacheConfig.splitMetadata
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class CacheModule(implicit val p: Parameters) extends Module
|
|
||||||
with HasCacheParameters
|
|
||||||
abstract class CacheBundle(implicit val p: Parameters) extends ParameterizedBundle()(p)
|
|
||||||
with HasCacheParameters
|
|
||||||
|
|
||||||
abstract class ReplacementPolicy {
|
|
||||||
def way: UInt
|
|
||||||
def miss: Unit
|
|
||||||
def hit: Unit
|
|
||||||
}
|
|
||||||
|
|
||||||
class RandomReplacement(ways: Int) extends ReplacementPolicy {
|
|
||||||
private val replace = Wire(Bool())
|
|
||||||
replace := Bool(false)
|
|
||||||
val lfsr = LFSR16(replace)
|
|
||||||
|
|
||||||
def way = if(ways == 1) UInt(0) else lfsr(log2Up(ways)-1,0)
|
|
||||||
def miss = replace := Bool(true)
|
|
||||||
def hit = {}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class SeqReplacementPolicy {
|
|
||||||
def access(set: UInt): Unit
|
|
||||||
def update(valid: Bool, hit: Bool, set: UInt, way: UInt): Unit
|
|
||||||
def way: UInt
|
|
||||||
}
|
|
||||||
|
|
||||||
class SeqRandom(n_ways: Int) extends SeqReplacementPolicy {
|
|
||||||
val logic = new RandomReplacement(n_ways)
|
|
||||||
def access(set: UInt) = { }
|
|
||||||
def update(valid: Bool, hit: Bool, set: UInt, way: UInt) = {
|
|
||||||
when (valid && !hit) { logic.miss }
|
|
||||||
}
|
|
||||||
def way = logic.way
|
|
||||||
}
|
|
||||||
|
|
||||||
class PseudoLRU(n: Int)
|
|
||||||
{
|
|
||||||
require(isPow2(n))
|
|
||||||
val state_reg = Reg(Bits(width = n))
|
|
||||||
def access(way: UInt) {
|
|
||||||
state_reg := get_next_state(state_reg,way)
|
|
||||||
}
|
|
||||||
def get_next_state(state: UInt, way: UInt) = {
|
|
||||||
var next_state = state
|
|
||||||
var idx = UInt(1,1)
|
|
||||||
for (i <- log2Up(n)-1 to 0 by -1) {
|
|
||||||
val bit = way(i)
|
|
||||||
next_state = next_state.bitSet(idx, !bit)
|
|
||||||
idx = Cat(idx, bit)
|
|
||||||
}
|
|
||||||
next_state
|
|
||||||
}
|
|
||||||
def replace = get_replace_way(state_reg)
|
|
||||||
def get_replace_way(state: Bits) = {
|
|
||||||
var idx = UInt(1,1)
|
|
||||||
for (i <- 0 until log2Up(n))
|
|
||||||
idx = Cat(idx, state(idx))
|
|
||||||
idx(log2Up(n)-1,0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SeqPLRU(n_sets: Int, n_ways: Int) extends SeqReplacementPolicy {
|
|
||||||
val state = SeqMem(n_sets, Bits(width = n_ways-1))
|
|
||||||
val logic = new PseudoLRU(n_ways)
|
|
||||||
val current_state = Wire(Bits())
|
|
||||||
val plru_way = logic.get_replace_way(current_state)
|
|
||||||
val next_state = Wire(Bits())
|
|
||||||
|
|
||||||
def access(set: UInt) = {
|
|
||||||
current_state := Cat(state.read(set), Bits(0, width = 1))
|
|
||||||
}
|
|
||||||
|
|
||||||
def update(valid: Bool, hit: Bool, set: UInt, way: UInt) = {
|
|
||||||
val update_way = Mux(hit, way, plru_way)
|
|
||||||
next_state := logic.get_next_state(current_state, update_way)
|
|
||||||
when (valid) { state.write(set, next_state(n_ways-1,1)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
def way = plru_way
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class Metadata(implicit p: Parameters) extends CacheBundle()(p) {
|
|
||||||
val tag = Bits(width = tagBits)
|
|
||||||
}
|
|
||||||
|
|
||||||
class MetaReadReq(implicit p: Parameters) extends CacheBundle()(p) {
|
|
||||||
val idx = Bits(width = idxBits)
|
|
||||||
val way_en = Bits(width = nWays)
|
|
||||||
}
|
|
||||||
|
|
||||||
class MetaWriteReq[T <: Metadata](gen: T)(implicit p: Parameters) extends MetaReadReq()(p) {
|
|
||||||
val data = gen.cloneType
|
|
||||||
override def cloneType = new MetaWriteReq(gen)(p).asInstanceOf[this.type]
|
|
||||||
}
|
|
||||||
|
|
||||||
class MetadataArray[T <: Metadata](onReset: () => T)(implicit p: Parameters) extends CacheModule()(p) {
|
|
||||||
val rstVal = onReset()
|
|
||||||
val io = new Bundle {
|
|
||||||
val read = Decoupled(new MetaReadReq).flip
|
|
||||||
val write = Decoupled(new MetaWriteReq(rstVal)).flip
|
|
||||||
val resp = Vec(nWays, rstVal.cloneType).asOutput
|
|
||||||
}
|
|
||||||
val rst_cnt = Reg(init=UInt(0, log2Up(nSets+1)))
|
|
||||||
val rst = rst_cnt < UInt(nSets)
|
|
||||||
val waddr = Mux(rst, rst_cnt, io.write.bits.idx)
|
|
||||||
val wdata = Mux(rst, rstVal, io.write.bits.data).asUInt
|
|
||||||
val wmask = Mux(rst || Bool(nWays == 1), SInt(-1), io.write.bits.way_en.asSInt).toBools
|
|
||||||
val rmask = Mux(rst || Bool(nWays == 1), SInt(-1), io.read.bits.way_en.asSInt).toBools
|
|
||||||
when (rst) { rst_cnt := rst_cnt+UInt(1) }
|
|
||||||
|
|
||||||
val metabits = rstVal.getWidth
|
|
||||||
|
|
||||||
if (hasSplitMetadata) {
|
|
||||||
val tag_arrs = List.fill(nWays){ SeqMem(nSets, UInt(width = metabits)) }
|
|
||||||
val tag_readout = Wire(Vec(nWays,rstVal.cloneType))
|
|
||||||
(0 until nWays).foreach { (i) =>
|
|
||||||
when (rst || (io.write.valid && wmask(i))) {
|
|
||||||
tag_arrs(i).write(waddr, wdata)
|
|
||||||
}
|
|
||||||
io.resp(i) := rstVal.fromBits(tag_arrs(i).read(io.read.bits.idx, io.read.valid && rmask(i)))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val tag_arr = SeqMem(nSets, Vec(nWays, UInt(width = metabits)))
|
|
||||||
when (rst || io.write.valid) {
|
|
||||||
tag_arr.write(waddr, Vec.fill(nWays)(wdata), wmask)
|
|
||||||
}
|
|
||||||
io.resp := tag_arr.read(io.read.bits.idx, io.read.valid).map(rstVal.fromBits(_))
|
|
||||||
}
|
|
||||||
|
|
||||||
io.read.ready := !rst && !io.write.valid // so really this could be a 6T RAM
|
|
||||||
io.write.ready := !rst
|
|
||||||
}
|
|
||||||
|
|
||||||
case object L2DirectoryRepresentation extends Field[DirectoryRepresentation]
|
case object L2DirectoryRepresentation extends Field[DirectoryRepresentation]
|
||||||
|
|
||||||
trait HasOuterCacheParameters extends HasCacheParameters with HasCoherenceAgentParameters {
|
trait HasOuterCacheParameters extends HasCacheParameters with HasCoherenceAgentParameters {
|
180
src/main/scala/uncore/util/Cache.scala
Normal file
180
src/main/scala/uncore/util/Cache.scala
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
package uncore.util
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import config.{Parameters, Field}
|
||||||
|
import junctions.PAddrBits
|
||||||
|
import util.ParameterizedBundle
|
||||||
|
import uncore.constants._
|
||||||
|
|
||||||
|
case class CacheConfig(
|
||||||
|
nSets: Int,
|
||||||
|
nWays: Int,
|
||||||
|
rowBits: Int,
|
||||||
|
nTLBEntries: Int,
|
||||||
|
cacheIdBits: Int,
|
||||||
|
splitMetadata: Boolean)
|
||||||
|
case class CacheName(id: String) extends Field[CacheConfig]
|
||||||
|
case object CacheName extends Field[CacheName]
|
||||||
|
|
||||||
|
case object Replacer extends Field[() => ReplacementPolicy]
|
||||||
|
case object L2Replacer extends Field[() => SeqReplacementPolicy]
|
||||||
|
case object NPrimaryMisses extends Field[Int]
|
||||||
|
case object NSecondaryMisses extends Field[Int]
|
||||||
|
case object CacheBlockBytes extends Field[Int]
|
||||||
|
case object ECCCode extends Field[Option[Code]]
|
||||||
|
|
||||||
|
trait HasCacheParameters {
|
||||||
|
implicit val p: Parameters
|
||||||
|
val cacheConfig = p(p(CacheName))
|
||||||
|
val nSets = cacheConfig.nSets
|
||||||
|
val blockOffBits = log2Up(p(CacheBlockBytes))
|
||||||
|
val cacheIdBits = cacheConfig.cacheIdBits
|
||||||
|
val idxBits = log2Up(cacheConfig.nSets)
|
||||||
|
val untagBits = blockOffBits + cacheIdBits + idxBits
|
||||||
|
val tagBits = p(PAddrBits) - untagBits
|
||||||
|
val nWays = cacheConfig.nWays
|
||||||
|
val wayBits = log2Up(nWays)
|
||||||
|
val isDM = nWays == 1
|
||||||
|
val rowBits = cacheConfig.rowBits
|
||||||
|
val rowBytes = rowBits/8
|
||||||
|
val rowOffBits = log2Up(rowBytes)
|
||||||
|
val code = p(ECCCode).getOrElse(new IdentityCode)
|
||||||
|
val hasSplitMetadata = cacheConfig.splitMetadata
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class CacheModule(implicit val p: Parameters) extends Module
|
||||||
|
with HasCacheParameters
|
||||||
|
abstract class CacheBundle(implicit val p: Parameters) extends ParameterizedBundle()(p)
|
||||||
|
with HasCacheParameters
|
||||||
|
|
||||||
|
abstract class ReplacementPolicy {
|
||||||
|
def way: UInt
|
||||||
|
def miss: Unit
|
||||||
|
def hit: Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
class RandomReplacement(ways: Int) extends ReplacementPolicy {
|
||||||
|
private val replace = Wire(Bool())
|
||||||
|
replace := Bool(false)
|
||||||
|
val lfsr = LFSR16(replace)
|
||||||
|
|
||||||
|
def way = if(ways == 1) UInt(0) else lfsr(log2Up(ways)-1,0)
|
||||||
|
def miss = replace := Bool(true)
|
||||||
|
def hit = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class SeqReplacementPolicy {
|
||||||
|
def access(set: UInt): Unit
|
||||||
|
def update(valid: Bool, hit: Bool, set: UInt, way: UInt): Unit
|
||||||
|
def way: UInt
|
||||||
|
}
|
||||||
|
|
||||||
|
class SeqRandom(n_ways: Int) extends SeqReplacementPolicy {
|
||||||
|
val logic = new RandomReplacement(n_ways)
|
||||||
|
def access(set: UInt) = { }
|
||||||
|
def update(valid: Bool, hit: Bool, set: UInt, way: UInt) = {
|
||||||
|
when (valid && !hit) { logic.miss }
|
||||||
|
}
|
||||||
|
def way = logic.way
|
||||||
|
}
|
||||||
|
|
||||||
|
class PseudoLRU(n: Int)
|
||||||
|
{
|
||||||
|
require(isPow2(n))
|
||||||
|
val state_reg = Reg(Bits(width = n))
|
||||||
|
def access(way: UInt) {
|
||||||
|
state_reg := get_next_state(state_reg,way)
|
||||||
|
}
|
||||||
|
def get_next_state(state: UInt, way: UInt) = {
|
||||||
|
var next_state = state
|
||||||
|
var idx = UInt(1,1)
|
||||||
|
for (i <- log2Up(n)-1 to 0 by -1) {
|
||||||
|
val bit = way(i)
|
||||||
|
next_state = next_state.bitSet(idx, !bit)
|
||||||
|
idx = Cat(idx, bit)
|
||||||
|
}
|
||||||
|
next_state
|
||||||
|
}
|
||||||
|
def replace = get_replace_way(state_reg)
|
||||||
|
def get_replace_way(state: Bits) = {
|
||||||
|
var idx = UInt(1,1)
|
||||||
|
for (i <- 0 until log2Up(n))
|
||||||
|
idx = Cat(idx, state(idx))
|
||||||
|
idx(log2Up(n)-1,0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SeqPLRU(n_sets: Int, n_ways: Int) extends SeqReplacementPolicy {
|
||||||
|
val state = SeqMem(n_sets, Bits(width = n_ways-1))
|
||||||
|
val logic = new PseudoLRU(n_ways)
|
||||||
|
val current_state = Wire(Bits())
|
||||||
|
val plru_way = logic.get_replace_way(current_state)
|
||||||
|
val next_state = Wire(Bits())
|
||||||
|
|
||||||
|
def access(set: UInt) = {
|
||||||
|
current_state := Cat(state.read(set), Bits(0, width = 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
def update(valid: Bool, hit: Bool, set: UInt, way: UInt) = {
|
||||||
|
val update_way = Mux(hit, way, plru_way)
|
||||||
|
next_state := logic.get_next_state(current_state, update_way)
|
||||||
|
when (valid) { state.write(set, next_state(n_ways-1,1)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
def way = plru_way
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class Metadata(implicit p: Parameters) extends CacheBundle()(p) {
|
||||||
|
val tag = Bits(width = tagBits)
|
||||||
|
}
|
||||||
|
|
||||||
|
class MetaReadReq(implicit p: Parameters) extends CacheBundle()(p) {
|
||||||
|
val idx = Bits(width = idxBits)
|
||||||
|
val way_en = Bits(width = nWays)
|
||||||
|
}
|
||||||
|
|
||||||
|
class MetaWriteReq[T <: Metadata](gen: T)(implicit p: Parameters) extends MetaReadReq()(p) {
|
||||||
|
val data = gen.cloneType
|
||||||
|
override def cloneType = new MetaWriteReq(gen)(p).asInstanceOf[this.type]
|
||||||
|
}
|
||||||
|
|
||||||
|
class MetadataArray[T <: Metadata](onReset: () => T)(implicit p: Parameters) extends CacheModule()(p) {
|
||||||
|
val rstVal = onReset()
|
||||||
|
val io = new Bundle {
|
||||||
|
val read = Decoupled(new MetaReadReq).flip
|
||||||
|
val write = Decoupled(new MetaWriteReq(rstVal)).flip
|
||||||
|
val resp = Vec(nWays, rstVal.cloneType).asOutput
|
||||||
|
}
|
||||||
|
val rst_cnt = Reg(init=UInt(0, log2Up(nSets+1)))
|
||||||
|
val rst = rst_cnt < UInt(nSets)
|
||||||
|
val waddr = Mux(rst, rst_cnt, io.write.bits.idx)
|
||||||
|
val wdata = Mux(rst, rstVal, io.write.bits.data).asUInt
|
||||||
|
val wmask = Mux(rst || Bool(nWays == 1), SInt(-1), io.write.bits.way_en.asSInt).toBools
|
||||||
|
val rmask = Mux(rst || Bool(nWays == 1), SInt(-1), io.read.bits.way_en.asSInt).toBools
|
||||||
|
when (rst) { rst_cnt := rst_cnt+UInt(1) }
|
||||||
|
|
||||||
|
val metabits = rstVal.getWidth
|
||||||
|
|
||||||
|
if (hasSplitMetadata) {
|
||||||
|
val tag_arrs = List.fill(nWays){ SeqMem(nSets, UInt(width = metabits)) }
|
||||||
|
val tag_readout = Wire(Vec(nWays,rstVal.cloneType))
|
||||||
|
(0 until nWays).foreach { (i) =>
|
||||||
|
when (rst || (io.write.valid && wmask(i))) {
|
||||||
|
tag_arrs(i).write(waddr, wdata)
|
||||||
|
}
|
||||||
|
io.resp(i) := rstVal.fromBits(tag_arrs(i).read(io.read.bits.idx, io.read.valid && rmask(i)))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val tag_arr = SeqMem(nSets, Vec(nWays, UInt(width = metabits)))
|
||||||
|
when (rst || io.write.valid) {
|
||||||
|
tag_arr.write(waddr, Vec.fill(nWays)(wdata), wmask)
|
||||||
|
}
|
||||||
|
io.resp := tag_arr.read(io.read.bits.idx, io.read.valid).map(rstVal.fromBits(_))
|
||||||
|
}
|
||||||
|
|
||||||
|
io.read.ready := !rst && !io.write.valid // so really this could be a 6T RAM
|
||||||
|
io.write.ready := !rst
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
// See LICENSE for license details.
|
// See LICENSE for license details.
|
||||||
|
|
||||||
package uncore.agents
|
package uncore.util
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import util._
|
import util._
|
Loading…
Reference in New Issue
Block a user