Merge pull request #449 from ucb-bar/post-refactor-cleanup
Post refactor cleanup
This commit is contained in:
commit
76fa62a928
@ -36,7 +36,8 @@ env:
|
||||
- SUITE=RocketSuiteA
|
||||
- SUITE=RocketSuiteB
|
||||
- SUITE=RocketSuiteC
|
||||
- SUITE=GroundtestSuite
|
||||
- SUITE=GroundtestSuiteA
|
||||
- SUITE=GroundtestSuiteB
|
||||
- SUITE=UnittestSuite
|
||||
|
||||
# blacklist private branches
|
||||
|
@ -53,10 +53,14 @@ PROJECT=rocketchip
|
||||
CONFIGS=DefaultL2Config TinyConfig
|
||||
endif
|
||||
|
||||
ifeq ($(SUITE),GroundtestSuite)
|
||||
ifeq ($(SUITE),GroundtestSuiteA)
|
||||
PROJECT=groundtest
|
||||
CONFIGS=MemtestConfig MemtestBufferlessConfig MemtestStatelessConfig FancyMemtestConfig \
|
||||
BroadcastRegressionTestConfig BufferlessRegressionTestConfig CacheRegressionTestConfig \
|
||||
CONFIGS=MemtestConfig MemtestBufferlessConfig MemtestStatelessConfig FancyMemtestConfig
|
||||
endif
|
||||
|
||||
ifeq ($(SUITE),GroundtestSuiteB)
|
||||
PROJECT=groundtest
|
||||
CONFIGS=BroadcastRegressionTestConfig BufferlessRegressionTestConfig CacheRegressionTestConfig \
|
||||
ComparatorConfig ComparatorBufferlessConfig ComparatorL2Config ComparatorStatelessConfig
|
||||
endif
|
||||
|
||||
|
@ -52,6 +52,8 @@ def main():
|
||||
numFinished = numFinished + 1
|
||||
if numFinished == total:
|
||||
break
|
||||
elif line[0:12] == "using random":
|
||||
continue
|
||||
else:
|
||||
print line,
|
||||
|
||||
|
@ -11,6 +11,7 @@ import uncore.coherence._
|
||||
import uncore.agents._
|
||||
import uncore.devices._
|
||||
import uncore.converters._
|
||||
import uncore.util._
|
||||
import rocket._
|
||||
import util._
|
||||
import util.ConfigUtils._
|
||||
|
@ -3,7 +3,7 @@ package groundtest
|
||||
import Chisel._
|
||||
import uncore.tilelink._
|
||||
import uncore.constants._
|
||||
import uncore.agents._
|
||||
import uncore.util._
|
||||
import util._
|
||||
import config._
|
||||
|
||||
|
@ -6,6 +6,7 @@ import diplomacy._
|
||||
import uncore.tilelink._
|
||||
import uncore.coherence._
|
||||
import uncore.agents._
|
||||
import uncore.util._
|
||||
import uncore.devices.NTiles
|
||||
import junctions._
|
||||
import config._
|
||||
|
@ -6,9 +6,10 @@ import diplomacy._
|
||||
import coreplex._
|
||||
import uncore.devices.NTiles
|
||||
import uncore.tilelink2._
|
||||
import rocket.TileId
|
||||
import uncore.tilelink.TLId
|
||||
|
||||
case object TileId extends Field[Int]
|
||||
|
||||
class GroundTestCoreplex(implicit p: Parameters) extends BaseCoreplex {
|
||||
val tiles = List.tabulate(p(NTiles)) { i =>
|
||||
LazyModule(new GroundTestTile()(p.alterPartial({
|
||||
|
@ -3,7 +3,7 @@ package groundtest
|
||||
import Chisel._
|
||||
import uncore.tilelink._
|
||||
import uncore.constants._
|
||||
import uncore.agents._
|
||||
import uncore.util._
|
||||
import util._
|
||||
import rocket._
|
||||
import rocketchip._
|
||||
|
@ -3,7 +3,7 @@ package groundtest
|
||||
import Chisel._
|
||||
import rocket._
|
||||
import uncore.tilelink._
|
||||
import uncore.agents.CacheName
|
||||
import uncore.util.CacheName
|
||||
import uncore.tilelink2._
|
||||
import rocketchip.ExtMem
|
||||
import diplomacy._
|
||||
|
@ -5,7 +5,6 @@ package rocket
|
||||
import Chisel._
|
||||
import Chisel.ImplicitConversions._
|
||||
import diplomacy._
|
||||
import uncore.agents._
|
||||
import uncore.constants._
|
||||
import uncore.tilelink2._
|
||||
import uncore.util._
|
||||
|
@ -6,7 +6,7 @@ import Chisel._
|
||||
import config.{Parameters, Field}
|
||||
import diplomacy._
|
||||
import uncore.tilelink2._
|
||||
import uncore.agents._
|
||||
import uncore.util._
|
||||
import uncore.constants._
|
||||
import uncore.tilelink.{TLKey, TLId}
|
||||
import util.ParameterizedBundle
|
||||
|
@ -5,7 +5,6 @@ package rocket
|
||||
import Chisel._
|
||||
import Chisel.ImplicitConversions._
|
||||
import diplomacy._
|
||||
import uncore.agents._
|
||||
import uncore.constants._
|
||||
import uncore.tilelink._
|
||||
import uncore.tilelink2._
|
||||
@ -176,15 +175,18 @@ class MSHR(id: Int, edge: TLEdgeOut)(implicit cfg: DCacheConfig, p: Parameters)
|
||||
val req_tag = req.addr >> untagBits
|
||||
val req_block_addr = (req.addr >> blockOffBits) << blockOffBits
|
||||
val idx_match = req_idx === io.req_bits.addr(untagBits-1,blockOffBits)
|
||||
|
||||
val new_coh = Reg(init=ClientMetadata.onReset)
|
||||
val (_, shrink_param, coh_on_clear) = req.old_meta.coh.onCacheControl(M_FLUSH)
|
||||
val grow_param = new_coh.onAccess(req.cmd)._2
|
||||
val coh_on_grant = new_coh.onGrant(req.cmd, io.mem_grant.bits.param)
|
||||
// We only accept secondary misses if we haven't yet sent an Acquire to outer memory
|
||||
// or if the Acquire that was sent will obtain a Grant with sufficient permissions
|
||||
// to let us replay this new request. I.e. we don't handle multiple outstanding
|
||||
// Acquires on the same block for now.
|
||||
val cmd_requires_second_acquire =
|
||||
req.old_meta.coh.requiresAcquireOnSecondaryMiss(req.cmd, io.req_bits.cmd)
|
||||
// Track whether or not a secondary acquire will cause the coherence state
|
||||
// to go from clean to dirty.
|
||||
val dirties_coh = Reg(Bool())
|
||||
val (cmd_requires_second_acquire, is_hit_again, _, dirtier_coh, dirtier_cmd) =
|
||||
new_coh.onSecondaryAccess(req.cmd, io.req_bits.cmd)
|
||||
|
||||
val states_before_refill = Seq(s_wb_req, s_wb_resp, s_meta_clear)
|
||||
val (_, _, refill_done, refill_address_inc) = edge.addr_inc(io.mem_grant)
|
||||
val sec_rdy = idx_match &&
|
||||
@ -197,19 +199,6 @@ class MSHR(id: Int, edge: TLEdgeOut)(implicit cfg: DCacheConfig, p: Parameters)
|
||||
rpq.io.enq.bits := io.req_bits
|
||||
rpq.io.deq.ready := (io.replay.ready && state === s_drain_rpq) || state === s_invalid
|
||||
|
||||
// TODO clean all this coh state business up
|
||||
val new_coh_state = Reg(init=ClientMetadata.onReset)
|
||||
val grow_param = Reg(init=UInt(0))
|
||||
val coh_on_grant = Mux(dirties_coh,
|
||||
ClientMetadata.maximum,
|
||||
req.old_meta.coh.onGrant(req.cmd, io.mem_grant.bits.param))
|
||||
val (is_hit, missed_param, coh_on_hit) = io.req_bits.old_meta.coh.onAccess(io.req_bits.cmd)
|
||||
val (needs_wb, _, _) = io.req_bits.old_meta.coh.onCacheControl(M_FLUSH)
|
||||
val (_, shrink_param, _) = req.old_meta.coh.onCacheControl(M_FLUSH)
|
||||
val (hit_again, missed_again_param, _) = req.old_meta.coh.onCacheControl(io.req_bits.cmd)
|
||||
val (_, _, clear_coh_state) = req.old_meta.coh.onCacheControl(M_FLUSH)
|
||||
val (_, after_wb_param, _) = ClientMetadata.onReset.onAccess(req.cmd)
|
||||
|
||||
when (state === s_drain_rpq && !rpq.io.deq.valid) {
|
||||
state := s_invalid
|
||||
}
|
||||
@ -221,14 +210,13 @@ class MSHR(id: Int, edge: TLEdgeOut)(implicit cfg: DCacheConfig, p: Parameters)
|
||||
state := s_meta_write_resp
|
||||
}
|
||||
when (state === s_refill_resp && refill_done) {
|
||||
new_coh := coh_on_grant
|
||||
state := s_meta_write_req
|
||||
new_coh_state := coh_on_grant
|
||||
}
|
||||
when (io.mem_acquire.fire()) { // s_refill_req
|
||||
state := s_refill_resp
|
||||
}
|
||||
when (state === s_meta_clear && io.meta_write.ready) {
|
||||
grow_param := after_wb_param
|
||||
state := s_refill_req
|
||||
}
|
||||
when (state === s_wb_resp && io.mem_grant.valid) {
|
||||
@ -241,24 +229,26 @@ class MSHR(id: Int, edge: TLEdgeOut)(implicit cfg: DCacheConfig, p: Parameters)
|
||||
//If we get a secondary miss that needs more permissions before we've sent
|
||||
// out the primary miss's Acquire, we can upgrade the permissions we're
|
||||
// going to ask for in s_refill_req
|
||||
when(cmd_requires_second_acquire) {
|
||||
req.cmd := io.req_bits.cmd
|
||||
when(!hit_again) { grow_param := missed_again_param }
|
||||
req.cmd := dirtier_cmd
|
||||
when (is_hit_again) {
|
||||
new_coh := dirtier_coh
|
||||
}
|
||||
dirties_coh := dirties_coh || isWrite(io.req_bits.cmd)
|
||||
}
|
||||
when (io.req_pri_val && io.req_pri_rdy) {
|
||||
req := io.req_bits
|
||||
dirties_coh := isWrite(io.req_bits.cmd)
|
||||
val old_coh = io.req_bits.old_meta.coh
|
||||
val needs_wb = old_coh.onCacheControl(M_FLUSH)._1
|
||||
val (is_hit, _, coh_on_hit) = old_coh.onAccess(io.req_bits.cmd)
|
||||
when (io.req_bits.tag_match) {
|
||||
when (is_hit) { // set dirty bit
|
||||
new_coh := coh_on_hit
|
||||
state := s_meta_write_req
|
||||
new_coh_state := coh_on_hit
|
||||
}.otherwise { // upgrade permissions
|
||||
new_coh := old_coh
|
||||
state := s_refill_req
|
||||
grow_param := missed_param
|
||||
}
|
||||
}.otherwise { // writback if necessary and refill
|
||||
new_coh := ClientMetadata.onReset
|
||||
state := Mux(needs_wb, s_wb_req, s_meta_clear)
|
||||
}
|
||||
}
|
||||
@ -285,7 +275,7 @@ class MSHR(id: Int, edge: TLEdgeOut)(implicit cfg: DCacheConfig, p: Parameters)
|
||||
|
||||
io.meta_write.valid := state.isOneOf(s_meta_write_req, s_meta_clear)
|
||||
io.meta_write.bits.idx := req_idx
|
||||
io.meta_write.bits.data.coh := Mux(state === s_meta_clear, clear_coh_state, new_coh_state)
|
||||
io.meta_write.bits.data.coh := Mux(state === s_meta_clear, coh_on_clear, new_coh)
|
||||
io.meta_write.bits.data.tag := io.tag
|
||||
io.meta_write.bits.way_en := req.way_en
|
||||
|
||||
|
@ -6,7 +6,7 @@ import Chisel._
|
||||
import config._
|
||||
import util._
|
||||
import Chisel.ImplicitConversions._
|
||||
import uncore.agents.PseudoLRU
|
||||
import uncore.util.PseudoLRU
|
||||
|
||||
case object BtbKey extends Field[BtbParameters]
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
package rocket
|
||||
|
||||
import Chisel._
|
||||
import uncore.agents._
|
||||
import uncore.util.PseudoLRU
|
||||
import uncore.constants._
|
||||
import util._
|
||||
import Chisel.ImplicitConversions._
|
||||
|
@ -5,7 +5,7 @@ package rocket
|
||||
import Chisel._
|
||||
import uncore.tilelink._
|
||||
import uncore.constants._
|
||||
import uncore.agents.CacheName
|
||||
import uncore.util.CacheName
|
||||
import util._
|
||||
import Chisel.ImplicitConversions._
|
||||
import config._
|
||||
|
@ -4,7 +4,7 @@ package rocket
|
||||
|
||||
import Chisel._
|
||||
import uncore.devices._
|
||||
import uncore.agents.CacheName
|
||||
import uncore.util.CacheName
|
||||
import uncore.constants._
|
||||
import uncore.tilelink2._
|
||||
import util._
|
||||
|
@ -6,7 +6,7 @@ import Chisel._
|
||||
import diplomacy._
|
||||
import uncore.tilelink._
|
||||
import uncore.tilelink2._
|
||||
import uncore.agents._
|
||||
import uncore.util.{CacheName, CacheBlockBytes}
|
||||
import uncore.converters._
|
||||
import uncore.devices._
|
||||
import util._
|
||||
@ -14,7 +14,6 @@ import config._
|
||||
import scala.collection.mutable.ListBuffer
|
||||
|
||||
case object BuildRoCC extends Field[Seq[RoccParameters]]
|
||||
case object TileId extends Field[Int]
|
||||
|
||||
case class RoccParameters(
|
||||
opcodes: OpcodeSet,
|
||||
@ -30,7 +29,6 @@ class RocketTile(tileId: Int)(implicit p: Parameters) extends LazyModule {
|
||||
val dcacheParams = coreParams.alterPartial({
|
||||
case CacheName => CacheName("L1D")
|
||||
case TLId => "L1toL2"
|
||||
case TileId => tileId // TODO using this messes with Heirarchical P&R: change to io.hartid?
|
||||
})
|
||||
val icacheParams = coreParams.alterPartial({
|
||||
case CacheName => CacheName("L1I")
|
||||
|
@ -8,8 +8,7 @@ import Chisel.ImplicitConversions._
|
||||
import scala.math._
|
||||
import config._
|
||||
import diplomacy._
|
||||
import uncore.agents._
|
||||
import uncore.coherence._
|
||||
import uncore.util._
|
||||
import uncore.tilelink2._
|
||||
|
||||
case object PgLevels extends Field[Int]
|
||||
|
@ -5,186 +5,14 @@ package uncore.agents
|
||||
import Chisel._
|
||||
import scala.reflect.ClassTag
|
||||
import junctions.PAddrBits
|
||||
import util.ParameterizedBundle
|
||||
import uncore.util.AMOALU
|
||||
import uncore.coherence._
|
||||
import uncore.tilelink._
|
||||
import uncore.constants._
|
||||
import uncore.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]
|
||||
|
||||
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]
|
||||
|
||||
trait HasOuterCacheParameters extends HasCacheParameters with HasCoherenceAgentParameters {
|
@ -88,12 +88,6 @@ class ClientMetadata extends Bundle {
|
||||
Cat(wr, toT) -> Dirty))
|
||||
}
|
||||
|
||||
/** Does a secondary miss on the block require another Acquire message */
|
||||
def requiresAcquireOnSecondaryMiss(first_cmd: UInt, second_cmd: UInt): Bool = {
|
||||
import MemoryOpCategories._
|
||||
isWriteIntent(second_cmd) && !isWriteIntent(first_cmd)
|
||||
}
|
||||
|
||||
/** Does this cache have permissions on this block sufficient to perform op,
|
||||
* and what to do next (Acquire message param or updated metadata). */
|
||||
def onAccess(cmd: UInt): (Bool, UInt, ClientMetadata) = {
|
||||
@ -101,6 +95,20 @@ class ClientMetadata extends Bundle {
|
||||
(r._1, r._2, ClientMetadata(r._2))
|
||||
}
|
||||
|
||||
/** Does a secondary miss on the block require another Acquire message */
|
||||
def onSecondaryAccess(first_cmd: UInt, second_cmd: UInt): (Bool, Bool, UInt, ClientMetadata, UInt) = {
|
||||
import MemoryOpCategories._
|
||||
val r1 = growStarter(first_cmd)
|
||||
val r2 = growStarter(second_cmd)
|
||||
val needs_second_acq = isWriteIntent(second_cmd) && !isWriteIntent(first_cmd)
|
||||
val hit_again = r1._1 && r2._1
|
||||
val dirties = categorize(second_cmd) === wr
|
||||
val biggest_grow_param = Mux(dirties, r2._2, r1._2)
|
||||
val dirtiest_state = ClientMetadata(biggest_grow_param)
|
||||
val dirtiest_cmd = Mux(dirties, second_cmd, first_cmd)
|
||||
(needs_second_acq, hit_again, biggest_grow_param, dirtiest_state, dirtiest_cmd)
|
||||
}
|
||||
|
||||
/** Metadata change on a returned Grant */
|
||||
def onGrant(cmd: UInt, param: UInt): ClientMetadata = ClientMetadata(growFinisher(cmd, param))
|
||||
|
||||
|
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.
|
||||
|
||||
package uncore.agents
|
||||
package uncore.util
|
||||
|
||||
import Chisel._
|
||||
import util._
|
Loading…
Reference in New Issue
Block a user