Merge pull request #39 from OpenXiangShan/ecc
ecc: integrate ecc to ctrlUnit
This commit is contained in:
commit
779921a972
|
@ -60,6 +60,7 @@ abstract class BaseMSHRIO[T_RESULT <: BaseDirResult, T_DIR_W <: BaseDirWrite, T_
|
|||
val dirResult: Valid[T_RESULT] // = Flipped(ValidIO(new DirResult))
|
||||
val resps = Flipped(new MSHRResps)
|
||||
val nestedwb = Input(new NestedWriteback)
|
||||
val ecc = Output(new EccInfo)
|
||||
}
|
||||
|
||||
abstract class BaseMSHR[T_RESULT <: BaseDirResult, T_DIR_W <: BaseDirWrite, T_TAG_W <: BaseTagWrite](
|
||||
|
|
|
@ -27,6 +27,7 @@ class CtrlUnitImp(wrapper: CtrlUnit) extends LazyModuleImp(wrapper) {
|
|||
|
||||
val req = IO(DecoupledIO(new CtrlReq()))
|
||||
val resp = IO(Flipped(DecoupledIO(new CtrlResp())))
|
||||
val ecc = IO(Flipped(DecoupledIO(new EccInfo())))
|
||||
|
||||
val node = wrapper.node
|
||||
val ctlnode = wrapper.ctlnode
|
||||
|
@ -66,10 +67,14 @@ class CtrlUnitImp(wrapper: CtrlUnit) extends LazyModuleImp(wrapper) {
|
|||
val ctl_way = RegInit(0.U(64.W))
|
||||
val ctl_dir = RegInit(0.U(64.W))
|
||||
val ctl_data = Seq.fill(cacheParams.blockBytes / 8){ RegInit(0.U(64.W)) }
|
||||
val ctl_ecc = RegInit(0.U(64.W))
|
||||
val ctl_client = RegInit(0.U(64.W))
|
||||
val ctl_cmd = RegInit(0.U(64.W))
|
||||
|
||||
val ecc_code = RegInit(0.U(64.W)) // assume non-zero as ECC error
|
||||
val ecc_tag = RegInit(0.U(64.W))
|
||||
val ecc_set = RegInit(0.U(64.W))
|
||||
val ecc_way = RegInit(0.U(64.W))
|
||||
|
||||
val cmd_in_valid = RegInit(false.B)
|
||||
val cmd_in_ready = WireInit(false.B)
|
||||
val cmd_out_valid = RegInit(false.B)
|
||||
|
@ -80,8 +85,10 @@ class CtrlUnitImp(wrapper: CtrlUnit) extends LazyModuleImp(wrapper) {
|
|||
|
||||
val ctl_config_regs = (
|
||||
Seq(ctl_tag, ctl_set, ctl_way) ++
|
||||
ctl_data ++ Seq(ctl_dir, ctl_ecc, ctl_client)
|
||||
).map(reg => RegField(64, reg, RegWriteFn(reg)))
|
||||
ctl_data ++
|
||||
Seq(ctl_dir, ctl_client) ++
|
||||
Seq(ecc_code, ecc_tag, ecc_set, ecc_way)
|
||||
).map(reg => RegField(64, reg, RegWriteFn(reg)))
|
||||
|
||||
ctlnode.regmap(
|
||||
0x000 -> RegFieldGroup(
|
||||
|
@ -106,6 +113,7 @@ class CtrlUnitImp(wrapper: CtrlUnit) extends LazyModuleImp(wrapper) {
|
|||
cmd_out_valid := true.B
|
||||
}
|
||||
resp.ready := !cmd_out_valid
|
||||
ecc.ready := ecc_code === 0.U // Block multiple ecc req
|
||||
req.valid := cmd_in_valid
|
||||
req.bits.cmd := ctl_cmd
|
||||
req.bits.data.zip(ctl_data).foreach(x => x._1 := x._2)
|
||||
|
@ -115,7 +123,7 @@ class CtrlUnitImp(wrapper: CtrlUnit) extends LazyModuleImp(wrapper) {
|
|||
req.bits.dir := ctl_dir
|
||||
req.bits.client := ctl_client
|
||||
|
||||
when(resp.fire()){
|
||||
when(resp.fire()) {
|
||||
switch(resp.bits.cmd){
|
||||
is(CacheCMD.CMD_R_S_TAG){
|
||||
ctl_tag := resp.bits.data(0)
|
||||
|
@ -134,6 +142,10 @@ class CtrlUnitImp(wrapper: CtrlUnit) extends LazyModuleImp(wrapper) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
when(ecc.fire()) {
|
||||
ecc_code := ecc.bits.errCode
|
||||
}
|
||||
}
|
||||
|
||||
class CtrlReq() extends Bundle {
|
||||
|
@ -151,6 +163,14 @@ class CtrlResp() extends Bundle {
|
|||
val data = Vec(8, UInt(64.W))
|
||||
}
|
||||
|
||||
class EccInfo() extends Bundle {
|
||||
val errCode = UInt(8.W)
|
||||
def ERR_NO = 0.U(8.W)
|
||||
def ERR_SELF_DIR = 1.U(8.W)
|
||||
def ERR_CLIENT_DIR = 2.U(8.W)
|
||||
def ERR_DATA = 3.U(8.W)
|
||||
}
|
||||
|
||||
object CacheCMD {
|
||||
def CMD_R_S_TAG = 0.U(8.W)
|
||||
def CMD_R_C_TAG = 1.U(8.W)
|
||||
|
|
|
@ -36,6 +36,7 @@ class DataStorage(implicit p: Parameters) extends HuanCunModule {
|
|||
val sourceD_wdata = Input(new DSData)
|
||||
val sinkC_waddr = Flipped(DecoupledIO(new DSAddress))
|
||||
val sinkC_wdata = Input(new DSData)
|
||||
val ecc = Output(new EccInfo)
|
||||
})
|
||||
|
||||
/* Define some internal parameters */
|
||||
|
@ -133,6 +134,7 @@ class DataStorage(implicit p: Parameters) extends HuanCunModule {
|
|||
|
||||
val outData = Wire(Vec(nrBanks, UInt((8 * bankBytes).W)))
|
||||
val data_en = Wire(Vec(nrBanks, Bool()))
|
||||
val errVec = Wire(Vec(nrBanks, Bool()))
|
||||
|
||||
for (i <- 0 until nrBanks) {
|
||||
val en = reqs.map(_.bankEn(i)).reduce(_ || _) && SReg.sren()
|
||||
|
@ -151,11 +153,14 @@ class DataStorage(implicit p: Parameters) extends HuanCunModule {
|
|||
data_en(i) := SReg.pipe(en && !selectedReq.wen)
|
||||
val decode = dataCode.decode(bankedData(i).io.r.resp.data(0))
|
||||
outData(i) := RegEnable(decode.uncorrected, data_en(i))
|
||||
when(data_en(i)) {
|
||||
assert(!decode.error)
|
||||
}
|
||||
errVec(i) := decode.error
|
||||
// when(data_en(i)) {
|
||||
// assert(!decode.error)
|
||||
// }
|
||||
}
|
||||
|
||||
io.ecc.errCode := Mux(Cat(errVec).orR(), io.ecc.ERR_DATA, io.ecc.ERR_NO)
|
||||
|
||||
/* Pack out-data to channels */
|
||||
val sourceDlatch = RegNext(SReg.pipe(sourceD_rreq.bankEn))
|
||||
val sourceClatch = RegNext(SReg.pipe(sourceC_req.bankEn))
|
||||
|
|
|
@ -26,6 +26,7 @@ import freechips.rocketchip.diplomacy._
|
|||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util.{BundleField, BundleFieldBase, UIntToOH1}
|
||||
import huancun.prefetch._
|
||||
import huancun.utils.NoopNode
|
||||
|
||||
trait HasHuanCunParameters {
|
||||
val p: Parameters
|
||||
|
@ -195,6 +196,10 @@ class HuanCun(implicit p: Parameters) extends LazyModule with HasHuanCunParamete
|
|||
|
||||
val ctrl_unit = cacheParams.ctrl.map(_ => LazyModule(new CtrlUnit(node)))
|
||||
val ctlnode = ctrl_unit.map(_.ctlnode)
|
||||
if (ctlnode.nonEmpty) {
|
||||
val noopNode = LazyModule(new NoopNode())
|
||||
ctlnode.get := noopNode.clientNode
|
||||
}
|
||||
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
val sizeBytes = cacheParams.sets * cacheParams.ways * cacheParams.blockBytes
|
||||
|
@ -277,11 +282,16 @@ class HuanCun(implicit p: Parameters) extends LazyModule with HasHuanCunParamete
|
|||
val arb = Module(new Arbiter(new CtrlResp, slices.size))
|
||||
arb.io.in <> VecInit(slices.map(_.io.ctl_resp))
|
||||
c.module.resp <> arb.io.out
|
||||
|
||||
val ecc_arb = Module(new Arbiter(new EccInfo, slices.size))
|
||||
ecc_arb.io.in <> VecInit(slices.map(_.io.ctl_ecc))
|
||||
c.module.ecc <> ecc_arb.io.out
|
||||
}
|
||||
if(ctrl_unit.isEmpty){
|
||||
if (ctrl_unit.isEmpty) {
|
||||
slices.foreach(_.io.ctl_req <> DontCare)
|
||||
slices.foreach(_.io.ctl_req.valid := false.B)
|
||||
slices.foreach(_.io.ctl_resp.ready := false.B)
|
||||
slices.foreach(_.io.ctl_ecc.ready := false.B)
|
||||
}
|
||||
node.edges.in.headOption.foreach { n =>
|
||||
n.client.clients.zipWithIndex.foreach {
|
||||
|
|
|
@ -23,6 +23,7 @@ import chipsalliance.rocketchip.config.Parameters
|
|||
import chisel3._
|
||||
import chisel3.util._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util.leftOR
|
||||
import huancun.noninclusive.{MSHR, ProbeHelper, SliceCtrl}
|
||||
import huancun.prefetch._
|
||||
|
||||
|
@ -33,18 +34,10 @@ class Slice()(implicit p: Parameters) extends HuanCunModule {
|
|||
val prefetch = prefetchOpt.map(_ => Flipped(new PrefetchIO))
|
||||
val ctl_req = Flipped(DecoupledIO(new CtrlReq()))
|
||||
val ctl_resp = DecoupledIO(new CtrlResp())
|
||||
val ctl_ecc = DecoupledIO(new EccInfo())
|
||||
})
|
||||
|
||||
val ctrl = cacheParams.ctrl.map(_ => Module(new SliceCtrl()))
|
||||
if(ctrl.nonEmpty){
|
||||
ctrl.get.io.req <> io.ctl_req
|
||||
io.ctl_resp <> ctrl.get.io.resp
|
||||
} else {
|
||||
io.ctl_req <> DontCare
|
||||
io.ctl_resp <> DontCare
|
||||
io.ctl_req.ready := false.B
|
||||
io.ctl_resp.valid := false.B
|
||||
}
|
||||
|
||||
def ctrl_arb[T <: Data](source: DecoupledIO[T], ctrl: Option[DecoupledIO[T]]): DecoupledIO[T] ={
|
||||
if(ctrl.nonEmpty){
|
||||
|
@ -558,4 +551,22 @@ class Slice()(implicit p: Parameters) extends HuanCunModule {
|
|||
|
||||
sinkA.io.a_pb_pop <> sourceA.io.pb_pop
|
||||
sinkA.io.a_pb_beat <> sourceA.io.pb_beat
|
||||
|
||||
if (ctrl.nonEmpty) {
|
||||
ctrl.get.io.req <> io.ctl_req
|
||||
io.ctl_resp <> ctrl.get.io.resp
|
||||
io.ctl_ecc <> DontCare
|
||||
val eccMask = Cat(ms.map(m => m.io.ecc.errCode =/= 0.U && m.io.status.valid))
|
||||
val valid_eccMask = ~(leftOR(eccMask) << 1) & eccMask
|
||||
val ms_errCode = VecInit(ms.map(_.io.ecc.errCode))(OHToUInt(valid_eccMask))
|
||||
io.ctl_ecc.bits.errCode := Mux(dataStorage.io.ecc.errCode =/= 0.U, dataStorage.io.ecc.errCode, ms_errCode)
|
||||
io.ctl_ecc.valid := Cat(eccMask).orR()
|
||||
} else {
|
||||
io.ctl_req <> DontCare
|
||||
io.ctl_resp <> DontCare
|
||||
io.ctl_ecc <> DontCare
|
||||
io.ctl_req.ready := false.B
|
||||
io.ctl_resp.valid := false.B
|
||||
io.ctl_ecc.valid := false.B
|
||||
}
|
||||
}
|
||||
|
|
|
@ -694,12 +694,23 @@ class MSHR()(implicit p: Parameters) extends BaseMSHR[DirResult, SelfDirWrite, S
|
|||
})
|
||||
}
|
||||
|
||||
def handleEcc() = {
|
||||
// assert(!io.dirResult.bits.self.hit || !io.dirResult.bits.self.error)
|
||||
// io.dirResult.bits.clients.foreach(r => assert(!r.hit || !r.error))
|
||||
when(io.dirResult.bits.self.hit && io.dirResult.bits.self.error) {
|
||||
io.ecc.errCode := io.ecc.ERR_SELF_DIR
|
||||
}
|
||||
when(Cat(io.dirResult.bits.clients.map{r => r.hit && r.error}).orR()) {
|
||||
io.ecc.errCode := io.ecc.ERR_CLIENT_DIR
|
||||
}
|
||||
}
|
||||
|
||||
io.ecc.errCode := io.ecc.ERR_NO
|
||||
|
||||
when(io.dirResult.valid) {
|
||||
|
||||
reset_all_flags()
|
||||
|
||||
assert(!io.dirResult.bits.self.hit || !io.dirResult.bits.self.error)
|
||||
io.dirResult.bits.clients.foreach(r => assert(!r.hit || !r.error))
|
||||
handleEcc()
|
||||
|
||||
when(req.fromC) {
|
||||
c_schedule()
|
||||
|
|
|
@ -85,6 +85,8 @@ class SliceCtrl()(implicit p: Parameters) extends HuanCunModule {
|
|||
io.dir_read.bits.idOH := Cat(req_reg.way, "b11".U)
|
||||
io.dir_read.bits.tag := req_reg.tag
|
||||
io.dir_read.bits.set := req_reg.set
|
||||
io.dir_read.bits.way := req_reg.way
|
||||
io.dir_read.bits.wayMode := false.B // TODO: it seems incorrect
|
||||
io.dir_read.bits.replacerInfo := DontCare
|
||||
io.dir_read.bits.source := DontCare
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package huancun.utils
|
||||
|
||||
import chipsalliance.rocketchip.config.Parameters
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
|
||||
class NoopNode()(implicit p: Parameters) extends LazyModule {
|
||||
|
||||
val clientParameters = TLMasterPortParameters.v1(
|
||||
Seq(TLMasterParameters.v1(
|
||||
name = "dcache",
|
||||
sourceId = IdRange(0, 1)
|
||||
))
|
||||
)
|
||||
|
||||
val clientNode = TLClientNode(Seq(clientParameters))
|
||||
|
||||
lazy val module = new LazyModuleImp(this)
|
||||
}
|
Loading…
Reference in New Issue