1
0

Separate tag ECC and data ECC options (#761)

This commit is contained in:
Andrew Waterman 2017-05-23 12:51:48 -07:00 committed by Henry Cook
parent 940614625e
commit b2b4c1abcd
5 changed files with 29 additions and 20 deletions

View File

@ -44,7 +44,9 @@ class DCache(val scratch: () => Option[AddressSet] = () => None)(implicit p: Par
} }
class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
require(rowBits == encRowBits) // no ECC // no ECC support
require(cacheParams.tagECC.isInstanceOf[IdentityCode])
require(cacheParams.dataECC.isInstanceOf[IdentityCode])
// tags // tags
val replacer = cacheParams.replacement val replacer = cacheParams.replacement

View File

@ -10,7 +10,7 @@ import diplomacy._
import tile._ import tile._
import uncore.constants._ import uncore.constants._
import uncore.tilelink2._ import uncore.tilelink2._
import uncore.util.Code import uncore.util.{Code, IdentityCode}
import util.{ParameterizedBundle, RandomReplacement} import util.{ParameterizedBundle, RandomReplacement}
import scala.collection.mutable.ListBuffer import scala.collection.mutable.ListBuffer
import scala.math.max import scala.math.max
@ -20,7 +20,8 @@ case class DCacheParams(
nWays: Int = 4, nWays: Int = 4,
rowBits: Int = 64, rowBits: Int = 64,
nTLBEntries: Int = 32, nTLBEntries: Int = 32,
ecc: Option[Code] = None, tagECC: Code = new IdentityCode,
dataECC: Code = new IdentityCode,
nMSHRs: Int = 1, nMSHRs: Int = 1,
nSDQ: Int = 17, nSDQ: Int = 17,
nRPQ: Int = 16, nRPQ: Int = 16,
@ -55,7 +56,7 @@ trait HasL1HellaCacheParameters extends HasL1CacheParameters with HasCoreParamet
def offsetlsb = wordOffBits def offsetlsb = wordOffBits
def rowWords = rowBits/wordBits def rowWords = rowBits/wordBits
def doNarrowRead = coreDataBits * nWays % rowBits == 0 def doNarrowRead = coreDataBits * nWays % rowBits == 0
def encDataBits = code.width(coreDataBits) def encDataBits = cacheParams.dataECC.width(coreDataBits)
def encRowBits = encDataBits*rowWords def encRowBits = encDataBits*rowWords
def lrscCycles = 32 // ISA requires 16-insn LRSC sequences to succeed def lrscCycles = 32 // ISA requires 16-insn LRSC sequences to succeed
def lrscBackoff = 3 // disallow LRSC reacquisition briefly def lrscBackoff = 3 // disallow LRSC reacquisition briefly

View File

@ -8,7 +8,7 @@ import config._
import diplomacy._ import diplomacy._
import tile._ import tile._
import uncore.tilelink2._ import uncore.tilelink2._
import uncore.util.Code import uncore.util._
import util._ import util._
import Chisel.ImplicitConversions._ import Chisel.ImplicitConversions._
@ -18,7 +18,8 @@ case class ICacheParams(
rowBits: Int = 128, rowBits: Int = 128,
nTLBEntries: Int = 32, nTLBEntries: Int = 32,
cacheIdBits: Int = 0, cacheIdBits: Int = 0,
ecc: Option[Code] = None, tagECC: Code = new IdentityCode,
dataECC: Code = new IdentityCode,
itimAddr: Option[BigInt] = None, itimAddr: Option[BigInt] = None,
blockBytes: Int = 64) extends L1CacheParams { blockBytes: Int = 64) extends L1CacheParams {
def replacement = new RandomReplacement(nWays) def replacement = new RandomReplacement(nWays)
@ -84,6 +85,9 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer)
val edge_in = outer.slaveNode.map(_.edgesIn.head) val edge_in = outer.slaveNode.map(_.edgesIn.head)
val tl_in = io.tl_in.map(_.head) val tl_in = io.tl_in.map(_.head)
val tECC = cacheParams.tagECC
val dECC = cacheParams.dataECC
require(isPow2(nSets) && isPow2(nWays)) require(isPow2(nSets) && isPow2(nWays))
require(isPow2(coreInstBytes)) require(isPow2(coreInstBytes))
require(!usingVM || pgIdxBits >= untagBits) require(!usingVM || pgIdxBits >= untagBits)
@ -141,11 +145,10 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer)
v v
} }
val entagbits = code.width(tagBits) val tag_array = SeqMem(nSets, Vec(nWays, Bits(width = tECC.width(tagBits))))
val tag_array = SeqMem(nSets, Vec(nWays, Bits(width = entagbits)))
val tag_rdata = tag_array.read(s0_vaddr(untagBits-1,blockOffBits), !refill_done && s0_valid) val tag_rdata = tag_array.read(s0_vaddr(untagBits-1,blockOffBits), !refill_done && s0_valid)
when (refill_done) { when (refill_done) {
val tag = code.encode(refill_tag) val tag = tECC.encode(refill_tag)
tag_array.write(refill_idx, Vec.fill(nWays)(tag), Vec.tabulate(nWays)(repl_way === _)) tag_array.write(refill_idx, Vec.fill(nWays)(tag), Vec.tabulate(nWays)(repl_way === _))
} }
@ -162,7 +165,7 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer)
val s1_tag_disparity = Wire(Vec(nWays, Bool())) val s1_tag_disparity = Wire(Vec(nWays, Bool()))
val wordBits = coreInstBits * fetchWidth val wordBits = coreInstBits * fetchWidth
val s1_dout = Wire(Vec(nWays, UInt(width = code.width(wordBits)))) val s1_dout = Wire(Vec(nWays, UInt(width = dECC.width(wordBits))))
val s0_slaveAddr = tl_in.map(_.a.bits.address).getOrElse(0.U) val s0_slaveAddr = tl_in.map(_.a.bits.address).getOrElse(0.U)
val s1s3_slaveAddr = Reg(UInt(width = log2Ceil(outer.size))) val s1s3_slaveAddr = Reg(UInt(width = log2Ceil(outer.size)))
@ -176,13 +179,13 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer)
lineInScratchpad(scratchpadLine(s1s3_slaveAddr)) && scratchpadWay(s1s3_slaveAddr) === i, lineInScratchpad(scratchpadLine(s1s3_slaveAddr)) && scratchpadWay(s1s3_slaveAddr) === i,
addrInScratchpad(io.s1_paddr) && scratchpadWay(io.s1_paddr) === i) addrInScratchpad(io.s1_paddr) && scratchpadWay(io.s1_paddr) === i)
val s1_vb = vb_array(Cat(UInt(i), s1_idx)) && !s1_slaveValid val s1_vb = vb_array(Cat(UInt(i), s1_idx)) && !s1_slaveValid
s1_tag_disparity(i) := s1_vb && code.decode(tag_rdata(i)).error s1_tag_disparity(i) := s1_vb && tECC.decode(tag_rdata(i)).error
s1_tag_hit(i) := scratchpadHit || (s1_vb && code.decode(tag_rdata(i)).uncorrected === s1_tag) s1_tag_hit(i) := scratchpadHit || (s1_vb && tECC.decode(tag_rdata(i)).uncorrected === s1_tag)
} }
assert(!(s1_valid || s1_slaveValid) || PopCount(s1_tag_hit zip s1_tag_disparity map { case (h, d) => h && !d }) <= 1) assert(!(s1_valid || s1_slaveValid) || PopCount(s1_tag_hit zip s1_tag_disparity map { case (h, d) => h && !d }) <= 1)
require(tl_out.d.bits.data.getWidth % wordBits == 0) require(tl_out.d.bits.data.getWidth % wordBits == 0)
val data_arrays = Seq.fill(tl_out.d.bits.data.getWidth / wordBits) { SeqMem(nSets * refillCycles, Vec(nWays, UInt(width = code.width(wordBits)))) } val data_arrays = Seq.fill(tl_out.d.bits.data.getWidth / wordBits) { SeqMem(nSets * refillCycles, Vec(nWays, UInt(width = dECC.width(wordBits)))) }
for ((data_array, i) <- data_arrays zipWithIndex) { for ((data_array, i) <- data_arrays zipWithIndex) {
def wordMatch(addr: UInt) = addr.extract(log2Ceil(tl_out.d.bits.data.getWidth/8)-1, log2Ceil(wordBits/8)) === i def wordMatch(addr: UInt) = addr.extract(log2Ceil(tl_out.d.bits.data.getWidth/8)-1, log2Ceil(wordBits/8)) === i
def row(addr: UInt) = addr(untagBits-1, blockOffBits-log2Ceil(refillCycles)) def row(addr: UInt) = addr(untagBits-1, blockOffBits-log2Ceil(refillCycles))
@ -195,7 +198,7 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer)
when (wen) { when (wen) {
val data = Mux(s3_slaveValid, s1s3_slaveData, tl_out.d.bits.data(wordBits*(i+1)-1, wordBits*i)) val data = Mux(s3_slaveValid, s1s3_slaveData, tl_out.d.bits.data(wordBits*(i+1)-1, wordBits*i))
val way = Mux(s3_slaveValid, scratchpadWay(s1s3_slaveAddr), repl_way) val way = Mux(s3_slaveValid, scratchpadWay(s1s3_slaveAddr), repl_way)
data_array.write(mem_idx, Vec.fill(nWays)(code.encode(data)), (0 until nWays).map(way === _)) data_array.write(mem_idx, Vec.fill(nWays)(dECC.encode(data)), (0 until nWays).map(way === _))
} }
val dout = data_array.read(mem_idx, !wen && s0_ren) val dout = data_array.read(mem_idx, !wen && s0_ren)
when (wordMatch(Mux(s1_slaveValid, s1s3_slaveAddr, io.s1_paddr))) { when (wordMatch(Mux(s1_slaveValid, s1s3_slaveAddr, io.s1_paddr))) {
@ -206,7 +209,8 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer)
// output signals // output signals
outer.latency match { outer.latency match {
case 1 => case 1 =>
require(code.isInstanceOf[uncore.util.IdentityCode]) require(tECC.isInstanceOf[uncore.util.IdentityCode])
require(dECC.isInstanceOf[uncore.util.IdentityCode])
require(outer.icacheParams.itimAddr.isEmpty) require(outer.icacheParams.itimAddr.isEmpty)
io.resp.bits := Mux1H(s1_tag_hit, s1_dout) io.resp.bits := Mux1H(s1_tag_hit, s1_dout)
io.resp.valid := s1_hit io.resp.valid := s1_hit
@ -219,7 +223,7 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer)
val s2_way_mux = Mux1H(s2_tag_hit, s2_dout) val s2_way_mux = Mux1H(s2_tag_hit, s2_dout)
val s2_tag_disparity = RegEnable(s1_tag_disparity, s1_valid || s1_slaveValid).asUInt.orR val s2_tag_disparity = RegEnable(s1_tag_disparity, s1_valid || s1_slaveValid).asUInt.orR
val s2_data_decoded = code.decode(s2_way_mux) val s2_data_decoded = dECC.decode(s2_way_mux)
val s2_disparity = s2_tag_disparity || s2_data_decoded.error val s2_disparity = s2_tag_disparity || s2_data_decoded.error
when (s2_valid && s2_disparity) { invalidate := true } when (s2_valid && s2_disparity) { invalidate := true }

View File

@ -669,6 +669,10 @@ class NonBlockingDCacheModule(outer: NonBlockingDCache) extends HellaCacheModule
require(isPow2(nWays)) // TODO: relax this require(isPow2(nWays)) // TODO: relax this
require(dataScratchpadSize == 0) require(dataScratchpadSize == 0)
// ECC is only supported on the data array
require(cacheParams.tagECC.isInstanceOf[IdentityCode])
val dECC = cacheParams.dataECC
val wb = Module(new WritebackUnit) val wb = Module(new WritebackUnit)
val prober = Module(new ProbeUnit) val prober = Module(new ProbeUnit)
val mshrs = Module(new MSHRFile) val mshrs = Module(new MSHRFile)
@ -759,7 +763,7 @@ class NonBlockingDCacheModule(outer: NonBlockingDCache) extends HellaCacheModule
data.io.write.valid := writeArb.io.out.valid data.io.write.valid := writeArb.io.out.valid
writeArb.io.out.ready := data.io.write.ready writeArb.io.out.ready := data.io.write.ready
data.io.write.bits := writeArb.io.out.bits data.io.write.bits := writeArb.io.out.bits
val wdata_encoded = (0 until rowWords).map(i => code.encode(writeArb.io.out.bits.data(coreDataBits*(i+1)-1,coreDataBits*i))) val wdata_encoded = (0 until rowWords).map(i => dECC.encode(writeArb.io.out.bits.data(coreDataBits*(i+1)-1,coreDataBits*i)))
data.io.write.bits.data := wdata_encoded.asUInt data.io.write.bits.data := wdata_encoded.asUInt
// tag read for new requests // tag read for new requests
@ -822,7 +826,7 @@ class NonBlockingDCacheModule(outer: NonBlockingDCache) extends HellaCacheModule
s2_data(w) := regs.asUInt s2_data(w) := regs.asUInt
} }
val s2_data_muxed = Mux1H(s2_tag_match_way, s2_data) val s2_data_muxed = Mux1H(s2_tag_match_way, s2_data)
val s2_data_decoded = (0 until rowWords).map(i => code.decode(s2_data_muxed(encDataBits*(i+1)-1,encDataBits*i))) val s2_data_decoded = (0 until rowWords).map(i => dECC.decode(s2_data_muxed(encDataBits*(i+1)-1,encDataBits*i)))
val s2_data_corrected = s2_data_decoded.map(_.corrected).asUInt val s2_data_corrected = s2_data_decoded.map(_.corrected).asUInt
val s2_data_uncorrected = s2_data_decoded.map(_.uncorrected).asUInt val s2_data_uncorrected = s2_data_decoded.map(_.uncorrected).asUInt
val s2_word_idx = if(doNarrowRead) UInt(0) else s2_req.addr(log2Up(rowWords*coreDataBytes)-1,log2Up(wordBytes)) val s2_word_idx = if(doNarrowRead) UInt(0) else s2_req.addr(log2Up(rowWords*coreDataBytes)-1,log2Up(wordBytes))

View File

@ -15,7 +15,6 @@ trait L1CacheParams {
def nWays: Int def nWays: Int
def rowBits: Int def rowBits: Int
def nTLBEntries: Int def nTLBEntries: Int
def ecc: Option[Code]
def blockBytes: Int def blockBytes: Int
} }
@ -36,7 +35,6 @@ trait HasL1CacheParameters {
def rowBits = cacheParams.rowBits def rowBits = cacheParams.rowBits
def rowBytes = rowBits/8 def rowBytes = rowBits/8
def rowOffBits = log2Up(rowBytes) def rowOffBits = log2Up(rowBytes)
def code = cacheParams.ecc.getOrElse(new IdentityCode)
def nTLBEntries = cacheParams.nTLBEntries def nTLBEntries = cacheParams.nTLBEntries
def cacheDataBits = p(SharedMemoryTLEdge).bundle.dataBits def cacheDataBits = p(SharedMemoryTLEdge).bundle.dataBits