diff --git a/src/main/scala/rocket/DCache.scala b/src/main/scala/rocket/DCache.scala index 2fe5e830..6702437a 100644 --- a/src/main/scala/rocket/DCache.scala +++ b/src/main/scala/rocket/DCache.scala @@ -15,16 +15,15 @@ import TLMessages._ class DCacheErrors(implicit p: Parameters) extends L1HellaCacheBundle()(p) with CanHaveErrors { - val correctable = (cacheParams.tagECC.canCorrect || cacheParams.dataECC.canCorrect).option(Valid(UInt(width = paddrBits))) - val uncorrectable = (cacheParams.tagECC.canDetect || cacheParams.dataECC.canDetect).option(Valid(UInt(width = paddrBits))) + val correctable = (cacheParams.tagCode.canCorrect || cacheParams.dataCode.canCorrect).option(Valid(UInt(width = paddrBits))) + val uncorrectable = (cacheParams.tagCode.canDetect || cacheParams.dataCode.canDetect).option(Valid(UInt(width = paddrBits))) val bus = Valid(UInt(width = paddrBits)) } class DCacheDataReq(implicit p: Parameters) extends L1HellaCacheBundle()(p) { - val eccBytes = cacheParams.dataECCBytes val addr = Bits(width = untagBits) val write = Bool() - val wdata = UInt(width = cacheParams.dataECC.width(eccBytes*8) * rowBytes/eccBytes) + val wdata = UInt(width = encBits * rowBytes / eccBytes) val wordMask = UInt(width = rowBytes / wordBytes) val eccMask = UInt(width = wordBytes / eccBytes) val way_en = Bits(width = nWays) @@ -37,9 +36,6 @@ class DCacheDataArray(implicit p: Parameters) extends L1HellaCacheModule()(p) { } require(rowBytes % wordBytes == 0) - val eccBits = cacheParams.dataECCBytes * 8 - val encBits = cacheParams.dataECC.width(eccBits) - val encWordBits = encBits * (wordBits / eccBits) val eccMask = if (eccBits == wordBits) Seq(true.B) else io.req.bits.eccMask.toBools val wMask = if (nWays == 1) eccMask else (0 until nWays).flatMap(i => eccMask.map(_ && io.req.bits.way_en(i))) val wWords = io.req.bits.wdata.grouped(encBits * (wordBits / eccBits)) @@ -69,11 +65,8 @@ class DCache(hartid: Int, val scratch: () => Option[AddressSet] = () => None, va } class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { - // no tag ECC support - val tECC = cacheParams.tagECC - val dECC = cacheParams.dataECC - val eccBytes = cacheParams.dataECCBytes - val eccBits = eccBytes * 8 + val tECC = cacheParams.tagCode + val dECC = cacheParams.dataCode require(isPow2(eccBytes) && eccBytes <= wordBytes) require(eccBytes == 1 || !dECC.isInstanceOf[IdentityCode]) val usingRMW = eccBytes > 1 || usingAtomicsInCache diff --git a/src/main/scala/rocket/HellaCache.scala b/src/main/scala/rocket/HellaCache.scala index dfd0a616..fd837632 100644 --- a/src/main/scala/rocket/HellaCache.scala +++ b/src/main/scala/rocket/HellaCache.scala @@ -19,8 +19,8 @@ case class DCacheParams( nWays: Int = 4, rowBits: Int = 64, nTLBEntries: Int = 32, - tagECC: Code = new IdentityCode, - dataECC: Code = new IdentityCode, + tagECC: Option[String] = None, + dataECC: Option[String] = None, dataECCBytes: Int = 1, nMSHRs: Int = 1, nSDQ: Int = 17, @@ -31,6 +31,9 @@ case class DCacheParams( pipelineWayMux: Boolean = false, scratch: Option[BigInt] = None) extends L1CacheParams { + def tagCode: Code = Code.fromString(tagECC) + def dataCode: Code = Code.fromString(dataECC) + def dataScratchpadBytes: Int = scratch.map(_ => nSets*blockBytes).getOrElse(0) def replacement = new RandomReplacement(nWays) @@ -58,7 +61,11 @@ trait HasL1HellaCacheParameters extends HasL1CacheParameters with HasCoreParamet def offsetlsb = wordOffBits def rowWords = rowBits/wordBits def doNarrowRead = coreDataBits * nWays % rowBits == 0 - def encDataBits = cacheParams.dataECC.width(coreDataBits) + def eccBytes = cacheParams.dataECCBytes + val eccBits = cacheParams.dataECCBytes * 8 + val encBits = cacheParams.dataCode.width(eccBits) + val encWordBits = encBits * (wordBits / eccBits) + def encDataBits = cacheParams.dataCode.width(coreDataBits) // NBDCache only def encRowBits = encDataBits*rowWords def lrscCycles = 32 // ISA requires 16-insn LRSC sequences to succeed def lrscBackoff = 3 // disallow LRSC reacquisition briefly diff --git a/src/main/scala/rocket/ICache.scala b/src/main/scala/rocket/ICache.scala index 2b5b1e65..fe1e3661 100644 --- a/src/main/scala/rocket/ICache.scala +++ b/src/main/scala/rocket/ICache.scala @@ -20,13 +20,15 @@ case class ICacheParams( rowBits: Int = 128, nTLBEntries: Int = 32, cacheIdBits: Int = 0, - tagECC: Code = new IdentityCode, - dataECC: Code = new IdentityCode, + tagECC: Option[String] = None, + dataECC: Option[String] = None, itimAddr: Option[BigInt] = None, prefetch: Boolean = false, blockBytes: Int = 64, latency: Int = 2, fetchBytes: Int = 4) extends L1CacheParams { + def tagCode: Code = Code.fromString(tagECC) + def dataCode: Code = Code.fromString(dataECC) def replacement = new RandomReplacement(nWays) } @@ -41,8 +43,8 @@ class ICacheReq(implicit p: Parameters) extends CoreBundle()(p) with HasL1ICache class ICacheErrors(implicit p: Parameters) extends CoreBundle()(p) with HasL1ICacheParameters with CanHaveErrors { - val correctable = (cacheParams.tagECC.canDetect || cacheParams.dataECC.canDetect).option(Valid(UInt(width = paddrBits))) - val uncorrectable = (cacheParams.itimAddr.nonEmpty && cacheParams.dataECC.canDetect).option(Valid(UInt(width = paddrBits))) + val correctable = (cacheParams.tagCode.canDetect || cacheParams.dataCode.canDetect).option(Valid(UInt(width = paddrBits))) + val uncorrectable = (cacheParams.itimAddr.nonEmpty && cacheParams.dataCode.canDetect).option(Valid(UInt(width = paddrBits))) } class ICache(val icacheParams: ICacheParams, val hartId: Int)(implicit p: Parameters) extends LazyModule { @@ -113,8 +115,8 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer) // Option.unzip does not exist :-( val (tl_in, edge_in) = outer.slaveNode.in.headOption.unzip - val tECC = cacheParams.tagECC - val dECC = cacheParams.dataECC + val tECC = cacheParams.tagCode + val dECC = cacheParams.dataCode require(isPow2(nSets) && isPow2(nWays)) require(!usingVM || pgIdxBits >= untagBits) diff --git a/src/main/scala/rocket/NBDcache.scala b/src/main/scala/rocket/NBDcache.scala index cf0fa9bb..7487daa3 100644 --- a/src/main/scala/rocket/NBDcache.scala +++ b/src/main/scala/rocket/NBDcache.scala @@ -668,8 +668,8 @@ class NonBlockingDCacheModule(outer: NonBlockingDCache) extends HellaCacheModule require(dataScratchpadSize == 0) // ECC is only supported on the data array - require(cacheParams.tagECC.isInstanceOf[IdentityCode]) - val dECC = cacheParams.dataECC + require(cacheParams.tagCode.isInstanceOf[IdentityCode]) + val dECC = cacheParams.dataCode val wb = Module(new WritebackUnit) val prober = Module(new ProbeUnit) diff --git a/src/main/scala/rocket/RocketCore.scala b/src/main/scala/rocket/RocketCore.scala index afde776f..5a4ac2e4 100644 --- a/src/main/scala/rocket/RocketCore.scala +++ b/src/main/scala/rocket/RocketCore.scala @@ -572,7 +572,7 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p) sboard.clear(ll_wen, ll_waddr) def id_sboard_clear_bypass(r: UInt) = { // ll_waddr arrives late when D$ has ECC, so reshuffle the hazard check - if (tileParams.dcache.get.dataECC.isInstanceOf[IdentityCode]) ll_wen && ll_waddr === r + if (!tileParams.dcache.get.dataECC.isDefined) ll_wen && ll_waddr === r else div.io.resp.fire() && div.io.resp.bits.tag === r || dmem_resp_replay && dmem_resp_xpu && dmem_resp_waddr === r } val id_sboard_hazard = checkHazards(hazard_targets, rd => sboard.read(rd) && !id_sboard_clear_bypass(rd)) diff --git a/src/main/scala/util/ECC.scala b/src/main/scala/util/ECC.scala index 6245513f..a3b39890 100644 --- a/src/main/scala/util/ECC.scala +++ b/src/main/scala/util/ECC.scala @@ -178,3 +178,15 @@ trait CanHaveErrors extends Bundle { val correctable: Option[ValidIO[UInt]] val uncorrectable: Option[ValidIO[UInt]] } + +object Code { + def fromString(s: Option[String]): Code = fromString(s.getOrElse("none")) + def fromString(s: String): Code = s.toLowerCase match { + case "none" => new IdentityCode + case "identity" => new IdentityCode + case "parity" => new ParityCode + case "sec" => new SECCode + case "secded" => new SECDEDCode + case _ => throw new IllegalArgumentException("Unknown ECC type") + } +}