未验证 提交 41b68474 编写于 作者: W William Wang 提交者: GitHub

dcache: use sram to build ecc array (#1382)

* dcache: use sram to build ecc array

* MainPipe: latch s1_encTag to last until s1_fire
Authored-by: Nzhanglinjuan <zhanglinjuan20s@ict.ac.cn>
上级 10551d4e
......@@ -419,7 +419,6 @@ class DCacheImp(outer: DCache) extends LazyModuleImp(outer) with HasDCacheParame
val atomicsReplayUnit = Module(new AtomicsReplayEntry)
val mainPipe = Module(new MainPipe)
val refillPipe = Module(new RefillPipe)
// val replacePipe = Module(new ReplacePipe)
val missQueue = Module(new MissQueue(edge))
val probeQueue = Module(new ProbeQueue(edge))
val wb = Module(new WritebackQueue(edge))
......@@ -665,18 +664,15 @@ class DCacheImp(outer: DCache) extends LazyModuleImp(outer) with HasDCacheParame
val cacheOpDecoder = Module(new CSRCacheOpDecoder("dcache", CacheInstrucion.COP_ID_DCACHE))
cacheOpDecoder.io.csr <> io.csr
bankedDataArray.io.cacheOp.req := cacheOpDecoder.io.cache.req
metaArray.io.cacheOp.req := cacheOpDecoder.io.cache.req
tagArray.io.cacheOp.req := cacheOpDecoder.io.cache.req
cacheOpDecoder.io.cache.resp.valid := bankedDataArray.io.cacheOp.resp.valid ||
metaArray.io.cacheOp.resp.valid ||
tagArray.io.cacheOp.resp.valid
cacheOpDecoder.io.cache.resp.bits := Mux1H(List(
bankedDataArray.io.cacheOp.resp.valid -> bankedDataArray.io.cacheOp.resp.bits,
metaArray.io.cacheOp.resp.valid -> metaArray.io.cacheOp.resp.bits,
tagArray.io.cacheOp.resp.valid -> tagArray.io.cacheOp.resp.bits,
))
cacheOpDecoder.io.error := io.error
assert(!((bankedDataArray.io.cacheOp.resp.valid +& metaArray.io.cacheOp.resp.valid +& tagArray.io.cacheOp.resp.valid) > 1.U))
assert(!((bankedDataArray.io.cacheOp.resp.valid +& tagArray.io.cacheOp.resp.valid) > 1.U))
//----------------------------------------
// performance counters
......
......@@ -24,17 +24,6 @@ import utils.{HasPerfEvents, XSDebug, XSPerfAccumulate}
import xiangshan.L1CacheErrorInfo
class LoadPipe(id: Int)(implicit p: Parameters) extends DCacheModule with HasPerfEvents {
def metaBits = (new Meta).getWidth
def encMetaBits = cacheParams.tagCode.width((new MetaAndTag).getWidth) - tagBits
def getMeta(encMeta: UInt): UInt = {
require(encMeta.getWidth == encMetaBits)
encMeta(metaBits - 1, 0)
}
def getECC(encMeta: UInt): UInt = {
require(encMeta.getWidth == encMetaBits)
encMeta(encMetaBits - 1, metaBits)
}
val io = IO(new DCacheBundle {
// incoming requests
val lsu = Flipped(new DCacheLoadIO)
......@@ -43,11 +32,11 @@ class LoadPipe(id: Int)(implicit p: Parameters) extends DCacheModule with HasPer
// meta and data array read port
val meta_read = DecoupledIO(new MetaReadReq)
val meta_resp = Input(Vec(nWays, UInt(encMetaBits.W)))
val meta_resp = Input(Vec(nWays, new Meta))
val error_flag_resp = Input(Vec(nWays, Bool()))
val tag_read = DecoupledIO(new TagReadReq)
val tag_resp = Input(Vec(nWays, UInt(tagBits.W)))
val tag_resp = Input(Vec(nWays, UInt(encTagBits.W)))
val banked_data_read = DecoupledIO(new L1BankedDataReadReq)
val banked_data_resp = Input(Vec(DCacheBanks, new L1BankedDataReadResult()))
......@@ -125,9 +114,10 @@ class LoadPipe(id: Int)(implicit p: Parameters) extends DCacheModule with HasPer
dump_pipeline_reqs("LoadPipe s1", s1_valid, s1_req)
// tag check
val meta_resp = VecInit(io.meta_resp.map(r => getMeta(r).asTypeOf(new Meta)))
val meta_resp = io.meta_resp
val tag_resp = io.tag_resp.map(r => r(tagBits - 1, 0))
def wayMap[T <: Data](f: Int => T) = VecInit((0 until nWays).map(f))
val s1_tag_eq_way = wayMap((w: Int) => io.tag_resp(w) === (get_tag(s1_addr))).asUInt
val s1_tag_eq_way = wayMap((w: Int) => tag_resp(w) === (get_tag(s1_addr))).asUInt
val s1_tag_match_way = wayMap((w: Int) => s1_tag_eq_way(w) && meta_resp(w).coh.isValid()).asUInt
val s1_tag_match = s1_tag_match_way.orR
assert(RegNext(!s1_valid || PopCount(s1_tag_match_way) <= 1.U), "tag should not match with more than 1 way")
......@@ -146,7 +136,7 @@ class LoadPipe(id: Int)(implicit p: Parameters) extends DCacheModule with HasPer
io.replace_way.set.valid := RegNext(s0_fire)
io.replace_way.set.bits := get_idx(s1_vaddr)
val s1_repl_way_en = UIntToOH(io.replace_way.way)
val s1_repl_tag = Mux1H(s1_repl_way_en, wayMap(w => io.tag_resp(w)))
val s1_repl_tag = Mux1H(s1_repl_way_en, wayMap(w => tag_resp(w)))
val s1_repl_coh = Mux1H(s1_repl_way_en, wayMap(w => meta_resp(w).coh))
val s1_need_replacement = !s1_tag_match
......@@ -170,10 +160,8 @@ class LoadPipe(id: Int)(implicit p: Parameters) extends DCacheModule with HasPer
val s1_will_send_miss_req = s1_valid && !s1_nack && !s1_nack_data && !s1_hit
// check ecc error
val ecc_resp = VecInit(io.meta_resp.map(r => getECC(r)))
val s1_ecc = Mux1H(s1_tag_match_way, wayMap((w: Int) => ecc_resp(w)))
val s1_eccMetaAndTag = Cat(s1_ecc, MetaAndTag(s1_hit_coh, get_tag(s1_addr)).asUInt)
val s1_tag_ecc_error = s1_hit && dcacheParameters.dataCode.decode(s1_eccMetaAndTag).error // error reported by tag ecc check
val s1_encTag = Mux1H(s1_tag_match_way, wayMap((w: Int) => io.tag_resp(w)))
val s1_tag_ecc_error = s1_hit && dcacheParameters.tagCode.decode(s1_encTag).error // error reported by tag ecc check
val s1_cache_flag_error = Mux(s1_need_replacement, false.B, s1_hit_error) // error reported by exist dcache error bit
val s1_error = s1_cache_flag_error || s1_tag_ecc_error
......
......@@ -86,9 +86,6 @@ class MainPipeReq(implicit p: Parameters) extends DCacheBundle {
}
class MainPipe(implicit p: Parameters) extends DCacheModule with HasPerfEvents {
val metaBits = (new Meta).getWidth
val encMetaBits = cacheParams.tagCode.width((new MetaAndTag).getWidth) - tagBits
val io = IO(new Bundle() {
// probe queue
val probe_req = Flipped(DecoupledIO(new MainPipeReq))
......@@ -113,13 +110,13 @@ class MainPipe(implicit p: Parameters) extends DCacheModule with HasPerfEvents {
val data_write = DecoupledIO(new L1BankedDataWriteReq)
val meta_read = DecoupledIO(new MetaReadReq)
val meta_resp = Input(Vec(nWays, UInt(encMetaBits.W)))
val meta_resp = Input(Vec(nWays, new Meta))
val meta_write = DecoupledIO(new MetaWriteReq)
val error_flag_resp = Input(Vec(nWays, Bool()))
val error_flag_write = DecoupledIO(new ErrorWriteReq)
val tag_read = DecoupledIO(new TagReadReq)
val tag_resp = Input(Vec(nWays, UInt(tagBits.W)))
val tag_resp = Input(Vec(nWays, UInt(encTagBits.W)))
val tag_write = DecoupledIO(new TagWriteReq)
// update state vec in replacement algo
......@@ -230,21 +227,14 @@ class MainPipe(implicit p: Parameters) extends DCacheModule with HasPerfEvents {
s1_s0_set_conflict := s1_valid && s0_idx === s1_idx
s1_s0_set_conflict_store := s1_valid && store_idx === s1_idx
def getMeta(encMeta: UInt): UInt = {
require(encMeta.getWidth == encMetaBits)
encMeta(metaBits - 1, 0)
}
def getECC(encMeta: UInt): UInt = {
require(encMeta.getWidth == encMetaBits)
encMeta(encMetaBits - 1, metaBits)
}
val meta_resp = Wire(Vec(nWays, (new Meta).asUInt()))
val tag_resp = Wire(Vec(nWays, UInt(tagBits.W)))
val ecc_meta_resp = Wire(Vec(nWays, UInt(encMetaBits.W)))
tag_resp := Mux(RegNext(s0_fire), io.tag_resp, RegNext(tag_resp))
ecc_meta_resp := Mux(RegNext(s0_fire), io.meta_resp, RegNext(ecc_meta_resp))
val meta_resp = ecc_meta_resp.map(getMeta(_))
val ecc_resp = ecc_meta_resp.map(getECC(_))
val ecc_resp = Wire(Vec(nWays, UInt(eccTagBits.W)))
meta_resp := Mux(RegNext(s0_fire), VecInit(io.meta_resp.map(_.asUInt)), RegNext(meta_resp))
tag_resp := Mux(RegNext(s0_fire), VecInit(io.tag_resp.map(r => r(tagBits - 1, 0))), RegNext(tag_resp))
ecc_resp := Mux(RegNext(s0_fire), VecInit(io.tag_resp.map(r => r(encTagBits - 1, tagBits))), RegNext(ecc_resp))
val enc_tag_resp = Wire(io.tag_resp.cloneType)
enc_tag_resp := Mux(RegNext(s0_fire), io.tag_resp, RegNext(enc_tag_resp))
def wayMap[T <: Data](f: Int => T) = VecInit((0 until nWays).map(f))
val s1_tag_eq_way = wayMap((w: Int) => tag_resp(w) === get_tag(s1_req.addr)).asUInt
......@@ -253,8 +243,7 @@ class MainPipe(implicit p: Parameters) extends DCacheModule with HasPerfEvents {
val s1_hit_tag = Mux(s1_tag_match, Mux1H(s1_tag_match_way, wayMap(w => tag_resp(w))), get_tag(s1_req.addr))
val s1_hit_coh = ClientMetadata(Mux(s1_tag_match, Mux1H(s1_tag_match_way, wayMap(w => meta_resp(w))), 0.U))
val s1_ecc = Mux1H(s1_tag_match_way, wayMap((w: Int) => ecc_resp(w)))
val s1_eccMetaAndTag = Cat(s1_ecc, MetaAndTag(s1_hit_coh, get_tag(s1_req.addr)).asUInt)
val s1_encTag = Mux1H(s1_tag_match_way, wayMap((w: Int) => enc_tag_resp(w)))
val s1_error = Mux(s1_tag_match, Mux1H(s1_tag_match_way, wayMap(w => io.error_flag_resp(w))), false.B)
// replacement policy
......@@ -637,7 +626,6 @@ class MainPipe(implicit p: Parameters) extends DCacheModule with HasPerfEvents {
io.meta_write.valid := s3_fire && update_meta
io.meta_write.bits.idx := s3_idx
io.meta_write.bits.way_en := s3_way_en
io.meta_write.bits.tag := get_tag(s3_req.addr)
io.meta_write.bits.meta.coh := new_coh
io.error_flag_write.valid := s3_fire && update_meta
......@@ -709,7 +697,7 @@ class MainPipe(implicit p: Parameters) extends DCacheModule with HasPerfEvents {
io.status.s3.bits.way_en := s3_way_en
io.error.ecc_error.valid := RegNext(s1_fire && s1_hit && !s1_req.replace) &&
RegNext(dcacheParameters.dataCode.decode(s1_eccMetaAndTag).error)
RegNext(dcacheParameters.tagCode.decode(s1_encTag).error)
io.error.ecc_error.bits := true.B
io.error.paddr.valid := io.error.ecc_error.valid
io.error.paddr.bits := s2_req.addr
......
......@@ -79,7 +79,6 @@ class RefillPipe(implicit p: Parameters) extends DCacheModule {
io.meta_write.bits.idx := idx
io.meta_write.bits.way_en := refill_w_req.way_en
io.meta_write.bits.meta := refill_w_req.meta
io.meta_write.bits.tag := tag
io.error_flag_write.valid := refill_w_valid
io.error_flag_write.bits.idx := idx
......
/***************************************************************************************
* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
* Copyright (c) 2020-2021 Peng Cheng Laboratory
*
* XiangShan is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
***************************************************************************************/
package xiangshan.cache
import chipsalliance.rocketchip.config.Parameters
import chisel3._
import chisel3.util._
import freechips.rocketchip.tilelink.{ClientMetadata, ClientStates}
import utils.{OneHot, ParallelMux}
class ReplacePipeReq(implicit p: Parameters) extends DCacheBundle {
val miss_id = UInt(log2Up(cfg.nMissEntries).W)
val way_en = UInt(DCacheWays.W)
// if dcache size > 32KB, vaddr is also needed for store
// vaddr is used to get extra index bits
val vaddr = UInt(VAddrBits.W)
val tag = UInt(tagBits.W) // tag of the block to be replaced
}
class ReplacePipeResp(implicit p: Parameters) extends DCacheBundle {
val miss_id = UInt(log2Up(cfg.nMissEntries).W)
}
class ReplacePipe(implicit p: Parameters) extends DCacheModule {
def metaAndTagOnReset = MetaAndTag(ClientMetadata.onReset, 0.U)
// enc bits encode both tag and meta, but is saved in meta array
val encMetaBits = cacheParams.tagCode.width(metaAndTagOnReset.getWidth) - tagBits
val metaBits = (new Meta).getWidth
val io = IO(new Bundle() {
// miss queue
val req = Flipped(DecoupledIO(new ReplacePipeReq))
// s1 resp when the block is already probed
// s2 resp when the block is sent to wbq
val resp = Vec(numReplaceRespPorts, ValidIO(new ReplacePipeResp))
// write-back queue
val wb = DecoupledIO(new WritebackReq)
// read data array, invalid meta array
val data_read = DecoupledIO(new L1BankedDataReadLineReq)
val data_resp = Input(Vec(DCacheBanks, new L1BankedDataReadResult))
val meta_read = DecoupledIO(new MetaReadReq)
val meta_resp = Input(Vec(nWays, UInt(encMetaBits.W)))
val meta_write = DecoupledIO(new MetaWriteReq)
val status = new Bundle() {
val s1_set, s2_set = ValidIO(UInt(idxBits.W))
}
})
require(numReplaceRespPorts >= 2)
val s0_fire = Wire(Bool())
val s1_ready, s2_ready = Wire(Bool())
val s1_valid, s2_valid = RegInit(false.B)
val s1_fire, s2_fire = Wire(Bool())
val s1_resp = io.resp.init.last
val s2_resp = io.resp.last
// meta array is made of regs, so meta write or read should always be ready
assert(RegNext(io.meta_write.ready))
assert(RegNext(io.meta_read.ready))
when (s0_fire) {
assert(PopCount(io.req.bits.way_en) <= 1.U)
}
// s0: read meta to be replaced
val s0_can_go = s1_ready && io.meta_read.ready
s0_fire := io.req.valid && s0_can_go
// s1: invalid meta that is going to be replaced
val s1_req = RegEnable(io.req.bits, s0_fire)
val s1_idx = addr_to_dcache_set(s1_req.vaddr)
val s1_coh = Wire(new ClientMetadata)
val s1_need_release = s1_coh.state =/= ClientStates.Nothing
val s1_need_data = if (dcacheParameters.alwaysReleaseData){
s1_coh.state =/= ClientStates.Nothing
} else {
s1_coh.state === ClientStates.Dirty
}
val s1_can_go_to_s2 = s1_need_release && s2_ready && (io.data_read.ready || !s1_need_data)
val s1_can_go_to_mq = !s1_need_release
val s1_can_go = s1_can_go_to_s2 || s1_can_go_to_mq
val s1_fire_to_s2 = s1_valid && s1_can_go_to_s2
val s1_fire_to_mq = s1_valid && s1_can_go_to_mq
s1_fire := s1_valid && s1_can_go
s1_ready := !s1_valid || s1_fire
when (s0_fire) {
s1_valid := true.B
}.elsewhen(s1_fire) {
s1_valid := false.B
}
val meta_resp_ecc = ParallelMux(s1_req.way_en.asBools zip io.meta_resp)
val meta_resp_raw = meta_resp_ecc(metaBits - 1, 0).asTypeOf(new Meta)
s1_coh := Mux(RegNext(s0_fire), meta_resp_raw.coh, RegNext(s1_coh))
// s2: invalid meta that is going to be replaced
val s2_req = RegEnable(s1_req, s1_fire_to_s2)
val s2_idx = addr_to_dcache_set(s2_req.vaddr)
val s2_coh = RegEnable(s1_coh, s1_fire_to_s2)
val s2_need_data = RegEnable(s1_need_data, s1_fire_to_s2)
val s2_can_go = /*io.meta_write.ready && */io.wb.ready
s2_fire := s2_valid && s2_can_go
s2_ready := !s2_valid || s2_fire
when (s1_fire_to_s2) {
s2_valid := true.B
}.elsewhen (s2_fire) {
s2_valid := false.B
}
val data_resp_raw = WireInit(VecInit(io.data_resp.map(_.raw_data)))
val s2_data = Wire(Vec(DCacheBanks, UInt(DCacheSRAMRowBits.W)))
s2_data := Mux(RegNext(s1_fire_to_s2), data_resp_raw, RegNext(s2_data))
io.req.ready := s0_can_go
io.data_read.valid := s1_valid && s1_need_data && s2_ready
io.data_read.bits.way_en := s1_req.way_en
io.data_read.bits.addr := s1_req.vaddr
io.data_read.bits.rmask := ~0.U(DCacheBanks.W)
io.meta_read.valid := io.req.valid && s1_ready
io.meta_read.bits.idx := addr_to_dcache_set(io.req.bits.vaddr)
io.meta_read.bits.way_en := io.req.bits.way_en
io.meta_write.valid := false.B // s2_valid && io.wb.ready
io.meta_write.bits.idx := s2_idx
io.meta_write.bits.way_en := s2_req.way_en
io.meta_write.bits.meta.coh := ClientMetadata.onReset
io.meta_write.bits.tag := s2_req.tag // only used to calculate ecc
io.wb.valid := s2_valid// && io.meta_write.ready
io.wb.bits.addr := get_block_addr(Cat(s2_req.tag, get_untag(s2_req.vaddr)))
val (_, release_param, _) = s2_coh.onCacheControl(M_FLUSH)
io.wb.bits.param := release_param
io.wb.bits.voluntary := true.B
io.wb.bits.hasData := s2_need_data
io.wb.bits.dirty := s2_coh.state === ClientStates.Dirty
io.wb.bits.data := s2_data.asUInt
io.wb.bits.delay_release := true.B
io.wb.bits.miss_id := s2_req.miss_id
s1_resp.valid := s1_fire_to_mq
s1_resp.bits.miss_id := s1_req.miss_id
s2_resp.valid := s2_fire
s2_resp.bits.miss_id := s2_req.miss_id
io.status.s1_set.valid := s1_valid
io.status.s1_set.bits := s1_idx
io.status.s2_set.valid := s2_valid
io.status.s2_set.bits := s2_idx
// Theoretically s1 and s2 won't resp to the same miss entry
assert(RegNext(!s1_resp.valid || !s2_resp.valid || s1_resp.bits.miss_id =/= s2_resp.bits.miss_id))
}
......@@ -35,20 +35,6 @@ object Meta {
}
}
class MetaAndTag(implicit p: Parameters) extends DCacheBundle {
val meta = new Meta
val tag = UInt(tagBits.W)
}
object MetaAndTag {
def apply(coh: ClientMetadata, tag: UInt)(implicit p: Parameters) = {
val x = Wire(new MetaAndTag)
x.meta.coh := coh
x.tag := tag
x
}
}
class MetaReadReq(implicit p: Parameters) extends DCacheBundle {
val idx = UInt(idxBits.W)
val way_en = UInt(nWays.W)
......@@ -56,94 +42,20 @@ class MetaReadReq(implicit p: Parameters) extends DCacheBundle {
class MetaWriteReq(implicit p: Parameters) extends MetaReadReq {
val meta = new Meta
val tag = UInt(tagBits.W) // used to calculate ecc
}
class ECCReadReq(implicit p: Parameters) extends MetaReadReq
class ECCWriteReq(implicit p: Parameters) extends ECCReadReq {
val ecc = UInt()
}
class ErrorWriteReq(implicit p: Parameters) extends MetaReadReq {
val error = Bool()
}
class AsynchronousECCArray(readPorts: Int, writePorts: Int)(implicit p: Parameters) extends DCacheModule {
def metaAndTagOnReset = MetaAndTag(ClientMetadata.onReset, 0.U)
// enc bits encode both tag and meta, but is saved in meta array
val metaAndTagBits = metaAndTagOnReset.getWidth
val encMetaAndTagBits = cacheParams.tagCode.width(metaAndTagBits)
val encMetaBits = encMetaAndTagBits - tagBits
val encBits = encMetaAndTagBits - metaAndTagBits
val io = IO(new Bundle() {
val read = Vec(readPorts, Flipped(ValidIO(new ECCReadReq)))
val resp = Output(Vec(readPorts, Vec(nWays, UInt(encBits.W))))
val write = Vec(writePorts, Flipped(ValidIO(new ECCWriteReq)))
val cacheOp = Flipped(new L1CacheInnerOpIO)
})
val ecc_array = Reg(Vec(nSets, Vec(nWays, UInt(encBits.W))))
when (reset.asBool()) {
ecc_array := 0.U.asTypeOf(ecc_array.cloneType)
}
io.read.zip(io.resp).foreach {
case (read, resp) =>
resp := RegEnable(ecc_array(read.bits.idx), read.valid)
}
io.write.foreach {
case write =>
write.bits.way_en.asBools.zipWithIndex.foreach {
case (wen, i) =>
when (write.valid && wen) {
ecc_array(write.bits.idx)(i) := write.bits.ecc
}
}
}
// deal with customized cache op
val cacheOpShouldResp = WireInit(false.B)
when (io.cacheOp.req.valid) {
when (isReadTagECC(io.cacheOp.req.bits.opCode)) {
cacheOpShouldResp := true.B
}
when (isWriteTagECC(io.cacheOp.req.bits.opCode)) {
ecc_array(io.cacheOp.req.bits.index)(io.cacheOp.req.bits.wayNum(4, 0)) :=
io.cacheOp.req.bits.write_tag_ecc
cacheOpShouldResp := true.B
}
}
io.cacheOp.resp.valid := RegNext(io.cacheOp.req.valid && cacheOpShouldResp)
io.cacheOp.resp.bits := DontCare
io.cacheOp.resp.bits.read_tag_ecc := Mux(
io.cacheOp.resp.valid,
RegNext(ecc_array(io.cacheOp.req.bits.index)(io.cacheOp.req.bits.wayNum(4, 0))),
0.U
)
}
class AsynchronousMetaArray(readPorts: Int, writePorts: Int)(implicit p: Parameters) extends DCacheModule {
def metaAndTagOnReset = MetaAndTag(ClientMetadata.onReset, 0.U)
// enc bits encode both tag and meta, but is saved in meta array
val metaAndTagBits = metaAndTagOnReset.getWidth
val encMetaAndTagBits = cacheParams.tagCode.width(metaAndTagBits)
val encMetaBits = encMetaAndTagBits - tagBits
val encBits = encMetaAndTagBits - metaAndTagBits
val io = IO(new Bundle() {
val read = Vec(readPorts, Flipped(DecoupledIO(new MetaReadReq)))
val resp = Output(Vec(readPorts, Vec(nWays, UInt(encMetaBits.W))))
val resp = Output(Vec(readPorts, Vec(nWays, new Meta)))
val write = Vec(writePorts, Flipped(DecoupledIO(new MetaWriteReq)))
// customized cache op port
val cacheOp = Flipped(new L1CacheInnerOpIO)
})
val meta_array = Reg(Vec(nSets, Vec(nWays, new Meta)))
val ecc_array = Module(new AsynchronousECCArray(readPorts, writePorts))
when (reset.asBool()) {
meta_array := 0.U.asTypeOf(meta_array.cloneType)
}
......@@ -151,21 +63,12 @@ class AsynchronousMetaArray(readPorts: Int, writePorts: Int)(implicit p: Paramet
(io.read.zip(io.resp)).zipWithIndex.foreach {
case ((read, resp), i) =>
read.ready := true.B
ecc_array.io.read(i).valid := read.fire()
ecc_array.io.read(i).bits := read.bits
resp := VecInit(RegEnable(meta_array(read.bits.idx), read.valid).zip(
ecc_array.io.resp(i)
).map { case (m, ecc) => Cat(ecc, m.asUInt) })
resp := RegEnable(meta_array(read.bits.idx), read.valid)
}
io.write.zip(ecc_array.io.write).foreach {
case (write, ecc_write) =>
io.write.foreach {
case write =>
write.ready := true.B
val ecc = cacheParams.tagCode.encode(MetaAndTag(write.bits.meta.coh, write.bits.tag).asUInt)(encMetaAndTagBits - 1, metaAndTagBits)
ecc_write.valid := write.fire()
ecc_write.bits.idx := write.bits.idx
ecc_write.bits.way_en := write.bits.way_en
ecc_write.bits.ecc := ecc
write.bits.way_en.asBools.zipWithIndex.foreach {
case (wen, i) =>
when (write.valid && wen) {
......@@ -173,8 +76,6 @@ class AsynchronousMetaArray(readPorts: Int, writePorts: Int)(implicit p: Paramet
}
}
}
ecc_array.io.cacheOp <> io.cacheOp
}
class ErrorArray(readPorts: Int, writePorts: Int)(implicit p: Parameters) extends DCacheModule {
......
......@@ -20,6 +20,7 @@ import chipsalliance.rocketchip.config.Parameters
import chisel3._
import chisel3.util._
import utils.SRAMTemplate
import xiangshan.cache.CacheInstrucion._
class TagReadReq(implicit p: Parameters) extends DCacheBundle {
val idx = UInt(idxBits.W)
......@@ -39,8 +40,10 @@ class TagArray(implicit p: Parameters) extends DCacheModule {
val read = Flipped(DecoupledIO(new TagReadReq))
val resp = Output(Vec(nWays, UInt(tagBits.W)))
val write = Flipped(DecoupledIO(new TagWriteReq))
// val ecc_write = Flipped(DecoupledIO(new TagEccWriteReq))
// val ecc_resp = Output(Vec(nWays, UInt(eccTagBits.W)))
// ecc
val ecc_read = Flipped(DecoupledIO(new TagReadReq))
val ecc_resp = Output(Vec(nWays, UInt(eccTagBits.W)))
val ecc_write = Flipped(DecoupledIO(new TagEccWriteReq))
})
// TODO: reset is unnecessary?
val rst_cnt = RegInit(0.U(log2Up(nSets + 1).W))
......@@ -57,14 +60,8 @@ class TagArray(implicit p: Parameters) extends DCacheModule {
val tag_array = Module(new SRAMTemplate(UInt(tagBits.W), set = nSets, way = nWays,
shouldReset = false, holdRead = false, singlePort = true))
// val ecc_array = Module(new SRAMTemplate(UInt(eccTagBits.W), set = nSets, way = nWays,
// shouldReset = false, holdRead = false, singlePort = true))
// tag write
def getECCFromEncTag(encTag: UInt) = {
require(encTag.getWidth == encTagBits)
encTag(encTagBits - 1, tagBits)
}
val ecc_array = Module(new SRAMTemplate(UInt(eccTagBits.W), set = nSets, way = nWays,
shouldReset = false, holdRead = false, singlePort = true))
val wen = rst || io.write.valid
tag_array.io.w.req.valid := wen
......@@ -73,12 +70,17 @@ class TagArray(implicit p: Parameters) extends DCacheModule {
data = wdata,
waymask = VecInit(wmask).asUInt()
)
// ecc_array.io.w.req.valid := wen
// ecc_array.io.w.req.bits.apply(
// setIdx = waddr,
// data = getECCFromEncTag(cacheParams.tagCode.encode(wdata)),
// waymask = VecInit(wmask).asUInt()
// )
val ecc_wen = rst || io.ecc_write.valid
val ecc_waddr = Mux(rst, rst_cnt, io.ecc_write.bits.idx)
val ecc_wdata = Mux(rst, rstVal, io.ecc_write.bits.ecc)
val ecc_wmask = Mux(rst || (nWays == 1).B, (-1).asSInt, io.ecc_write.bits.way_en.asSInt).asBools
ecc_array.io.w.req.valid := ecc_wen
ecc_array.io.w.req.bits.apply(
setIdx = ecc_waddr,
data = ecc_wdata,
waymask = VecInit(ecc_wmask).asUInt()
)
// tag read
val ren = io.read.fire()
......@@ -87,30 +89,21 @@ class TagArray(implicit p: Parameters) extends DCacheModule {
tag_array.io.r.req.bits.apply(setIdx = io.read.bits.idx)
io.resp := tag_array.io.r.resp.data
// ecc_array.io.r.req.valid := ren
// ecc_array.io.r.req.bits.apply(setIdx = io.read.bits.idx)
// io.ecc_resp := ecc_array.io.r.resp.data
//
// // cache op tag ecc write
// val ecc_force_wen = io.ecc_write.valid
// ecc_array.io.w.req.valid := ecc_force_wen
// when(ecc_force_wen){
// ecc_array.io.w.req.bits.apply(
// setIdx = io.ecc_write.bits.idx,
// data = io.ecc_write.bits.ecc,
// waymask = io.ecc_write.bits.way_en
// )
// }
val ecc_ren = io.ecc_read.fire()
ecc_array.io.r.req.valid := ecc_ren
ecc_array.io.r.req.bits.apply(setIdx = io.ecc_read.bits.idx)
io.ecc_resp := ecc_array.io.r.resp.data
io.write.ready := !rst
// io.ecc_write.ready := !rst
io.read.ready := !wen
io.ecc_write.ready := !rst
io.ecc_read.ready := !ecc_wen
}
class DuplicatedTagArray(readPorts: Int)(implicit p: Parameters) extends DCacheModule {
val io = IO(new Bundle() {
val read = Vec(readPorts, Flipped(DecoupledIO(new TagReadReq)))
val resp = Output(Vec(readPorts, Vec(nWays, UInt(tagBits.W))))
val resp = Output(Vec(readPorts, Vec(nWays, UInt(encTagBits.W))))
val write = Flipped(DecoupledIO(new TagWriteReq))
// customized cache op port
val cacheOp = Flipped(new L1CacheInnerOpIO)
......@@ -118,15 +111,29 @@ class DuplicatedTagArray(readPorts: Int)(implicit p: Parameters) extends DCacheM
val array = Seq.fill(readPorts) { Module(new TagArray) }
def getECCFromEncTag(encTag: UInt) = {
require(encTag.getWidth == encTagBits)
encTag(encTagBits - 1, tagBits)
}
for (i <- 0 until readPorts) {
// normal read / write
array(i).io.write.valid := io.write.valid
array(i).io.write.bits := io.write.bits
array(i).io.ecc_write.valid := io.write.valid
array(i).io.ecc_write.bits.idx := io.write.bits.idx
array(i).io.ecc_write.bits.way_en := io.write.bits.way_en
val ecc = getECCFromEncTag(cacheParams.tagCode.encode(io.write.bits.tag))
array(i).io.ecc_write.bits.ecc := ecc
array(i).io.read <> io.read(i)
io.resp(i) <> array(i).io.resp
array(i).io.ecc_read.valid := io.read(i).valid
array(i).io.ecc_read.bits := io.read(i).bits
io.resp(i) := (array(i).io.ecc_resp zip array(i).io.resp).map { case (e, r) => Cat(e, r) }
// extra ports for cache op
// array(i).io.ecc_write.valid := false.B
// array(i).io.ecc_write.bits := DontCare
io.read(i).ready := array(i).io.read.ready && array(i).io.ecc_read.ready
}
io.write.ready := true.B
......@@ -135,10 +142,7 @@ class DuplicatedTagArray(readPorts: Int)(implicit p: Parameters) extends DCacheM
io.cacheOp.resp.bits := DontCare
val cacheOpShouldResp = WireInit(false.B)
when(io.cacheOp.req.valid){
when(
CacheInstrucion.isReadTag(io.cacheOp.req.bits.opCode)/* ||
CacheInstrucion.isReadTagECC(io.cacheOp.req.bits.opCode)*/
){
when (isReadTag(io.cacheOp.req.bits.opCode)){
for (i <- 0 until readPorts) {
array(i).io.read.valid := true.B
array(i).io.read.bits.idx := io.cacheOp.req.bits.index
......@@ -146,7 +150,15 @@ class DuplicatedTagArray(readPorts: Int)(implicit p: Parameters) extends DCacheM
}
cacheOpShouldResp := true.B
}
when(CacheInstrucion.isWriteTag(io.cacheOp.req.bits.opCode)){
when (isReadTagECC(io.cacheOp.req.bits.opCode)) {
for (i <- 0 until readPorts) {
array(i).io.ecc_read.valid := true.B
array(i).io.ecc_read.bits.idx := io.cacheOp.req.bits.index
array(i).io.ecc_read.bits.way_en := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0))
}
cacheOpShouldResp := true.B
}
when (isWriteTag(io.cacheOp.req.bits.opCode)){
for (i <- 0 until readPorts) {
array(i).io.write.valid := true.B
array(i).io.write.bits.idx := io.cacheOp.req.bits.index
......@@ -155,18 +167,18 @@ class DuplicatedTagArray(readPorts: Int)(implicit p: Parameters) extends DCacheM
}
cacheOpShouldResp := true.B
}
// when(CacheInstrucion.isWriteTagECC(io.cacheOp.req.bits.opCode)){
// for (i <- 0 until readPorts) {
// array(i).io.ecc_write.valid := true.B
// array(i).io.ecc_write.bits.idx := io.cacheOp.req.bits.index
// array(i).io.ecc_write.bits.way_en := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0))
// array(i).io.ecc_write.bits.ecc := io.cacheOp.req.bits.write_tag_ecc
// }
// cacheOpShouldResp := true.B
// }
when(isWriteTagECC(io.cacheOp.req.bits.opCode)){
for (i <- 0 until readPorts) {
array(i).io.ecc_write.valid := true.B
array(i).io.ecc_write.bits.idx := io.cacheOp.req.bits.index
array(i).io.ecc_write.bits.way_en := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0))
array(i).io.ecc_write.bits.ecc := io.cacheOp.req.bits.write_tag_ecc
}
cacheOpShouldResp := true.B
}
}
io.cacheOp.resp.valid := RegNext(io.cacheOp.req.valid && cacheOpShouldResp)
io.cacheOp.resp.bits.read_tag_low := Mux(io.cacheOp.resp.valid, array(0).io.resp(io.cacheOp.req.bits.wayNum), 0.U)
// io.cacheOp.resp.bits.read_tag_ecc := Mux(io.cacheOp.resp.valid, array(0).io.ecc_resp(io.cacheOp.req.bits.wayNum), 0.U)
io.cacheOp.resp.bits.read_tag_low := Mux(io.cacheOp.resp.valid, array(0).io.resp(RegNext(io.cacheOp.req.bits.wayNum)), 0.U)
io.cacheOp.resp.bits.read_tag_ecc := Mux(io.cacheOp.resp.valid, array(0).io.ecc_resp(RegNext(io.cacheOp.req.bits.wayNum)), 0.U)
// TODO: deal with duplicated array
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册