167 lines
4.9 KiB
Scala
167 lines
4.9 KiB
Scala
// See LICENSE for license details.
|
|
|
|
package rocket
|
|
|
|
import Chisel._
|
|
import config.{Parameters, Field}
|
|
import diplomacy._
|
|
import uncore.tilelink2._
|
|
import uncore.util._
|
|
import uncore.constants._
|
|
import uncore.tilelink.{TLKey, TLId}
|
|
import util.ParameterizedBundle
|
|
|
|
case class DCacheConfig(
|
|
nMSHRs: Int = 1,
|
|
nSDQ: Int = 17,
|
|
nRPQ: Int = 16,
|
|
nMMIOs: Int = 1)
|
|
|
|
case object DCacheKey extends Field[DCacheConfig]
|
|
|
|
trait HasL1HellaCacheParameters extends HasCacheParameters with HasCoreParameters {
|
|
val outerDataBeats = p(TLKey(p(TLId))).dataBeats
|
|
val outerDataBits = p(TLKey(p(TLId))).dataBitsPerBeat
|
|
|
|
val refillCyclesPerBeat = outerDataBits/rowBits
|
|
require(refillCyclesPerBeat == 1)
|
|
|
|
val refillCycles = refillCyclesPerBeat*outerDataBeats
|
|
|
|
val cacheBlockBytes = p(CacheBlockBytes)
|
|
val lgCacheBlockBytes = log2Up(cacheBlockBytes)
|
|
|
|
val wordBits = xLen // really, xLen max
|
|
val wordBytes = wordBits/8
|
|
val wordOffBits = log2Up(wordBytes)
|
|
val beatBytes = cacheBlockBytes / outerDataBeats
|
|
val beatWords = beatBytes / wordBytes
|
|
val beatOffBits = log2Up(beatBytes)
|
|
val idxMSB = untagBits-1
|
|
val idxLSB = blockOffBits
|
|
val offsetmsb = idxLSB-1
|
|
val offsetlsb = wordOffBits
|
|
val rowWords = rowBits/wordBits
|
|
val doNarrowRead = coreDataBits * nWays % rowBits == 0
|
|
val encDataBits = code.width(coreDataBits)
|
|
val encRowBits = encDataBits*rowWords
|
|
val nIOMSHRs = 1
|
|
val lrscCycles = 32 // ISA requires 16-insn LRSC sequences to succeed
|
|
|
|
require(isPow2(nSets))
|
|
require(rowBits >= coreDataBits)
|
|
require(rowBits <= outerDataBits)
|
|
require(xLen <= outerDataBits) // would need offset addr for puts if data width < xlen
|
|
require(!usingVM || untagBits <= pgIdxBits)
|
|
}
|
|
|
|
abstract class L1HellaCacheModule(implicit val p: Parameters) extends Module
|
|
with HasL1HellaCacheParameters
|
|
|
|
abstract class L1HellaCacheBundle(implicit val p: Parameters) extends ParameterizedBundle()(p)
|
|
with HasL1HellaCacheParameters
|
|
|
|
class L1Metadata(implicit p: Parameters) extends Metadata()(p) with HasL1HellaCacheParameters {
|
|
val coh = new ClientMetadata
|
|
}
|
|
object L1Metadata {
|
|
def apply(tag: Bits, coh: ClientMetadata)(implicit p: Parameters) = {
|
|
val meta = Wire(new L1Metadata)
|
|
meta.tag := tag
|
|
meta.coh := coh
|
|
meta
|
|
}
|
|
}
|
|
|
|
class L1MetaReadReq(implicit p: Parameters) extends MetaReadReq {
|
|
val tag = Bits(width = tagBits)
|
|
override def cloneType = new L1MetaReadReq()(p).asInstanceOf[this.type] //TODO remove
|
|
}
|
|
|
|
class L1MetaWriteReq(implicit p: Parameters) extends
|
|
MetaWriteReq[L1Metadata](new L1Metadata)
|
|
|
|
trait HasCoreMemOp extends HasCoreParameters {
|
|
val addr = UInt(width = coreMaxAddrBits)
|
|
val tag = Bits(width = dcacheReqTagBits)
|
|
val cmd = Bits(width = M_SZ)
|
|
val typ = Bits(width = MT_SZ)
|
|
}
|
|
|
|
trait HasCoreData extends HasCoreParameters {
|
|
val data = Bits(width = coreDataBits)
|
|
}
|
|
|
|
class HellaCacheReq(implicit p: Parameters) extends HellaCacheReqInternal()(p) with HasCoreData
|
|
|
|
class HellaCacheResp(implicit p: Parameters) extends CoreBundle()(p)
|
|
with HasCoreMemOp
|
|
with HasCoreData {
|
|
val replay = Bool()
|
|
val has_data = Bool()
|
|
val data_word_bypass = Bits(width = coreDataBits)
|
|
val store_data = Bits(width = coreDataBits)
|
|
}
|
|
|
|
class AlignmentExceptions extends Bundle {
|
|
val ld = Bool()
|
|
val st = Bool()
|
|
}
|
|
|
|
class HellaCacheExceptions extends Bundle {
|
|
val ma = new AlignmentExceptions
|
|
val pf = new AlignmentExceptions
|
|
}
|
|
|
|
|
|
// interface between D$ and processor/DTLB
|
|
class HellaCacheIO(implicit p: Parameters) extends CoreBundle()(p) {
|
|
val req = Decoupled(new HellaCacheReq)
|
|
val s1_kill = Bool(OUTPUT) // kill previous cycle's req
|
|
val s1_data = Bits(OUTPUT, coreDataBits) // data for previous cycle's req
|
|
val s2_nack = Bool(INPUT) // req from two cycles ago is rejected
|
|
|
|
val resp = Valid(new HellaCacheResp).flip
|
|
val replay_next = Bool(INPUT)
|
|
val xcpt = (new HellaCacheExceptions).asInput
|
|
val invalidate_lr = Bool(OUTPUT)
|
|
val ordered = Bool(INPUT)
|
|
}
|
|
|
|
abstract class HellaCache(val cfg: DCacheConfig)(implicit val p: Parameters) extends LazyModule {
|
|
val node = TLClientNode(TLClientParameters(
|
|
sourceId = IdRange(0, cfg.nMSHRs + cfg.nMMIOs),
|
|
supportsProbe = TransferSizes(p(CacheBlockBytes))))
|
|
val module: HellaCacheModule
|
|
}
|
|
|
|
class HellaCacheBundle(outer: HellaCache)(implicit p: Parameters) extends Bundle {
|
|
val cpu = (new HellaCacheIO).flip
|
|
val ptw = new TLBPTWIO()
|
|
val mem = outer.node.bundleOut
|
|
}
|
|
|
|
class HellaCacheModule(outer: HellaCache)(implicit val p: Parameters) extends LazyModuleImp(outer)
|
|
with HasL1HellaCacheParameters {
|
|
implicit val cfg = outer.cfg
|
|
val io = new HellaCacheBundle(outer)
|
|
val tl_out = io.mem(0)
|
|
|
|
/* TODO
|
|
edge.manager.managers.foreach { m =>
|
|
if (m.supportsGet) {
|
|
require (m.supportsGet.contains(TransferSizes(1, tlDataBytes)))
|
|
....etc
|
|
}
|
|
}
|
|
*/
|
|
|
|
}
|
|
|
|
object HellaCache {
|
|
def apply(cfg: DCacheConfig, scratch: () => Option[AddressSet] = () => None)(implicit p: Parameters) = {
|
|
if (cfg.nMSHRs == 0) LazyModule(new DCache(cfg, scratch))
|
|
else LazyModule(new NonBlockingDCache(cfg))
|
|
}
|
|
}
|