1
0

Support eccBytes > 1

This commit is contained in:
Andrew Waterman 2017-06-28 02:06:52 -07:00
parent 8e4be40efc
commit b9a934ae28

View File

@ -13,11 +13,12 @@ import util._
import TLMessages._ import TLMessages._
class DCacheDataReq(implicit p: Parameters) extends L1HellaCacheBundle()(p) { class DCacheDataReq(implicit p: Parameters) extends L1HellaCacheBundle()(p) {
val eccBytes = cacheParams.dataECCBytes
val addr = Bits(width = untagBits) val addr = Bits(width = untagBits)
val write = Bool() val write = Bool()
val wdata = UInt(width = cacheParams.dataECC.width(cacheParams.dataECCBytes*8) * rowBytes/cacheParams.dataECCBytes) val wdata = UInt(width = cacheParams.dataECC.width(eccBytes*8) * rowBytes/eccBytes)
val wordMask = UInt(width = rowBytes / wordBytes) val wordMask = UInt(width = rowBytes / wordBytes)
val byteMask = UInt(width = wordBytes) val eccMask = UInt(width = wordBytes / eccBytes)
val way_en = Bits(width = nWays) val way_en = Bits(width = nWays)
} }
@ -31,7 +32,7 @@ class DCacheDataArray(implicit p: Parameters) extends L1HellaCacheModule()(p) {
val eccBits = cacheParams.dataECCBytes * 8 val eccBits = cacheParams.dataECCBytes * 8
val encBits = cacheParams.dataECC.width(eccBits) val encBits = cacheParams.dataECC.width(eccBits)
val encWordBits = encBits * (wordBits / eccBits) val encWordBits = encBits * (wordBits / eccBits)
val eccMask = if (eccBits == wordBits) Seq(true.B) else (0 until wordBytes by eccBits/8).map(io.req.bits.byteMask(_)) 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 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)) val wWords = io.req.bits.wdata.grouped(encBits * (wordBits / eccBits))
val addr = io.req.bits.addr >> rowOffBits val addr = io.req.bits.addr >> rowOffBits
@ -59,7 +60,9 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
val eccBytes = cacheParams.dataECCBytes val eccBytes = cacheParams.dataECCBytes
val eccBits = eccBytes * 8 val eccBits = eccBytes * 8
require(tECC.isInstanceOf[IdentityCode]) require(tECC.isInstanceOf[IdentityCode])
require(eccBytes == 1) require(isPow2(eccBytes) && eccBytes <= wordBytes)
require(eccBytes == 1 || !dECC.isInstanceOf[IdentityCode])
val usingRMW = eccBytes > 1 || usingAtomics
// tags // tags
val replacer = cacheParams.replacement val replacer = cacheParams.replacement
@ -93,7 +96,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
s1_req := io.cpu.req.bits s1_req := io.cpu.req.bits
s1_req.addr := Cat(io.cpu.req.bits.addr >> untagBits, metaReadArb.io.out.bits.idx, io.cpu.req.bits.addr(blockOffBits-1,0)) s1_req.addr := Cat(io.cpu.req.bits.addr >> untagBits, metaReadArb.io.out.bits.idx, io.cpu.req.bits.addr(blockOffBits-1,0))
} }
val s1_read = isRead(s1_req.cmd) val s1_read = needsRead(s1_req)
val s1_write = isWrite(s1_req.cmd) val s1_write = isWrite(s1_req.cmd)
val s1_readwrite = s1_read || s1_write val s1_readwrite = s1_read || s1_write
val s1_sfence = s1_req.cmd === M_SFENCE val s1_sfence = s1_req.cmd === M_SFENCE
@ -114,12 +117,13 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
val uncachedReqs = Seq.fill(maxUncachedInFlight) { Reg(new HellaCacheReq) } val uncachedReqs = Seq.fill(maxUncachedInFlight) { Reg(new HellaCacheReq) }
// hit initiation path // hit initiation path
dataArb.io.in(3).valid := io.cpu.req.valid && isRead(io.cpu.req.bits.cmd) val s0_read = needsRead(io.cpu.req.bits)
dataArb.io.in(3).valid := io.cpu.req.valid && s0_read
dataArb.io.in(3).bits.write := false dataArb.io.in(3).bits.write := false
dataArb.io.in(3).bits.addr := io.cpu.req.bits.addr dataArb.io.in(3).bits.addr := io.cpu.req.bits.addr
dataArb.io.in(3).bits.wordMask := UIntToOH(io.cpu.req.bits.addr.extract(rowOffBits-1,offsetlsb)) dataArb.io.in(3).bits.wordMask := UIntToOH(io.cpu.req.bits.addr.extract(rowOffBits-1,offsetlsb))
dataArb.io.in(3).bits.way_en := ~UInt(0, nWays) dataArb.io.in(3).bits.way_en := ~UInt(0, nWays)
when (!dataArb.io.in(3).ready && isRead(io.cpu.req.bits.cmd)) { io.cpu.req.ready := false } when (!dataArb.io.in(3).ready && s0_read) { io.cpu.req.ready := false }
metaReadArb.io.in(2).valid := io.cpu.req.valid metaReadArb.io.in(2).valid := io.cpu.req.valid
metaReadArb.io.in(2).bits.idx := io.cpu.req.bits.addr(idxMSB, idxLSB) metaReadArb.io.in(2).bits.idx := io.cpu.req.bits.addr(idxMSB, idxLSB)
metaReadArb.io.in(2).bits.way_en := ~UInt(0, nWays) metaReadArb.io.in(2).bits.way_en := ~UInt(0, nWays)
@ -193,7 +197,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
val (s2_hit, s2_grow_param, s2_new_hit_state) = s2_hit_state.onAccess(s2_req.cmd) val (s2_hit, s2_grow_param, s2_new_hit_state) = s2_hit_state.onAccess(s2_req.cmd)
val s2_data_decoded = decodeData(s2_data) val s2_data_decoded = decodeData(s2_data)
val s2_word_idx = s2_req.addr.extract(log2Up(rowBits/8)-1, log2Up(wordBytes)) val s2_word_idx = s2_req.addr.extract(log2Up(rowBits/8)-1, log2Up(wordBytes))
val s2_data_error = s2_read && (s2_data_decoded.map(_.error).grouped(wordBits/eccBits).map(_.reduce(_||_)).toSeq)(s2_word_idx) val s2_data_error = needsRead(s2_req) && (s2_data_decoded.map(_.error).grouped(wordBits/eccBits).map(_.reduce(_||_)).toSeq)(s2_word_idx)
val s2_data_corrected = (s2_data_decoded.map(_.corrected): Seq[UInt]).asUInt val s2_data_corrected = (s2_data_decoded.map(_.corrected): Seq[UInt]).asUInt
val s2_data_uncorrected = (s2_data_decoded.map(_.uncorrected): Seq[UInt]).asUInt val s2_data_uncorrected = (s2_data_decoded.map(_.uncorrected): Seq[UInt]).asUInt
val s2_valid_hit_pre_data_ecc = s2_valid_masked && s2_readwrite && s2_hit val s2_valid_hit_pre_data_ecc = s2_valid_masked && s2_readwrite && s2_hit
@ -246,16 +250,16 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
val pstore1_way = RegEnable(s1_hit_way, s1_valid_not_nacked && s1_write) val pstore1_way = RegEnable(s1_hit_way, s1_valid_not_nacked && s1_write)
val pstore1_mask = RegEnable(s1_mask, s1_valid_not_nacked && s1_write) val pstore1_mask = RegEnable(s1_mask, s1_valid_not_nacked && s1_write)
val pstore1_storegen_data = Wire(init = pstore1_data) val pstore1_storegen_data = Wire(init = pstore1_data)
val pstore1_amo = Bool(usingAtomics) && isRead(pstore1_cmd) val pstore1_rmw = Bool(usingRMW) && RegEnable(s1_read, s1_valid_not_nacked && s1_write)
val pstore1_valid = Wire(Bool()) val pstore1_valid = Wire(Bool())
val pstore2_valid = Reg(Bool()) val pstore2_valid = Reg(Bool())
any_pstore_valid := pstore1_valid || pstore2_valid any_pstore_valid := pstore1_valid || pstore2_valid
val pstore_drain_structural = pstore1_valid && pstore2_valid && ((s1_valid && s1_write) || pstore1_amo) val pstore_drain_structural = pstore1_valid && pstore2_valid && ((s1_valid && s1_write) || pstore1_rmw)
val pstore_drain_opportunistic = !(io.cpu.req.valid && isRead(io.cpu.req.bits.cmd)) val pstore_drain_opportunistic = !(io.cpu.req.valid && s0_read)
val pstore_drain_on_miss = releaseInFlight || io.cpu.s2_nack val pstore_drain_on_miss = releaseInFlight || io.cpu.s2_nack
val pstore_drain = val pstore_drain =
Bool(usingAtomics) && pstore_drain_structural || Bool(usingRMW) && pstore_drain_structural ||
(((pstore1_valid && !pstore1_amo) || pstore2_valid) && (pstore_drain_opportunistic || pstore_drain_on_miss)) (((pstore1_valid && !pstore1_rmw) || pstore2_valid) && (pstore_drain_opportunistic || pstore_drain_on_miss))
pstore1_valid := { pstore1_valid := {
val s2_store_valid = s2_valid_hit && s2_write && !s2_sc_fail val s2_store_valid = s2_valid_hit && s2_write && !s2_sc_fail
val pstore1_held = Reg(Bool()) val pstore1_held = Reg(Bool())
@ -275,13 +279,15 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
dataArb.io.in(0).bits.way_en := Mux(pstore2_valid, pstore2_way, pstore1_way) dataArb.io.in(0).bits.way_en := Mux(pstore2_valid, pstore2_way, pstore1_way)
dataArb.io.in(0).bits.wdata := Fill(rowWords, Mux(pstore2_valid, pstore2_storegen_data, pstore1_data)) dataArb.io.in(0).bits.wdata := Fill(rowWords, Mux(pstore2_valid, pstore2_storegen_data, pstore1_data))
dataArb.io.in(0).bits.wordMask := UIntToOH(Mux(pstore2_valid, pstore2_addr, pstore1_addr).extract(rowOffBits-1,offsetlsb)) dataArb.io.in(0).bits.wordMask := UIntToOH(Mux(pstore2_valid, pstore2_addr, pstore1_addr).extract(rowOffBits-1,offsetlsb))
dataArb.io.in(0).bits.byteMask := Mux(pstore2_valid, pstore2_storegen_mask, pstore1_mask) dataArb.io.in(0).bits.eccMask := eccMask(Mux(pstore2_valid, pstore2_storegen_mask, pstore1_mask))
// store->load RAW hazard detection // store->load RAW hazard detection
val s1_idx = s1_req.addr(idxMSB, wordOffBits) def s1Depends(addr: UInt, mask: UInt) =
addr(idxMSB, wordOffBits) === s1_req.addr(idxMSB, wordOffBits) &&
Mux(s1_write, (eccByteMask(mask) & eccByteMask(s1_mask)).orR, (mask & s1_mask).orR)
val s1_raw_hazard = s1_read && val s1_raw_hazard = s1_read &&
((pstore1_valid && pstore1_addr(idxMSB, wordOffBits) === s1_idx && (pstore1_mask & s1_mask).orR) || ((pstore1_valid && s1Depends(pstore1_addr, pstore1_mask)) ||
(pstore2_valid && pstore2_addr(idxMSB, wordOffBits) === s1_idx && (pstore2_storegen_mask & s1_mask).orR)) (pstore2_valid && s1Depends(pstore2_addr, pstore2_storegen_mask)))
when (s1_valid && s1_raw_hazard) { s1_nack := true } when (s1_valid && s1_raw_hazard) { s1_nack := true }
metaWriteArb.io.in(0).valid := (s2_valid_hit && s2_update_meta) || (s2_victimize && !s2_victim_dirty) metaWriteArb.io.in(0).valid := (s2_valid_hit && s2_update_meta) || (s2_victimize && !s2_victim_dirty)
@ -316,13 +322,13 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
M_XA_MAXU -> edge.Arithmetic(a_source, access_address, a_size, a_data, TLAtomics.MAXU)._2)) M_XA_MAXU -> edge.Arithmetic(a_source, access_address, a_size, a_data, TLAtomics.MAXU)._2))
} else { } else {
// If no managers support atomics, assert fail if processor asks for them // If no managers support atomics, assert fail if processor asks for them
assert (!(tl_out_a.valid && pstore1_amo && s2_write && s2_uncached)) assert (!(tl_out_a.valid && s2_read && s2_write && s2_uncached))
Wire(new TLBundleA(edge.bundle)) Wire(new TLBundleA(edge.bundle))
} }
tl_out_a.valid := (s2_valid_cached_miss && !s2_victim_dirty) || tl_out_a.valid := (s2_valid_cached_miss && !s2_victim_dirty) ||
(s2_valid_uncached && !uncachedInFlight.asUInt.andR) (s2_valid_uncached && !uncachedInFlight.asUInt.andR)
tl_out_a.bits := Mux(!s2_uncached, acquire, Mux(!s2_write, get, Mux(!pstore1_amo, put, atomics))) tl_out_a.bits := Mux(!s2_uncached, acquire, Mux(!s2_write, get, Mux(!s2_read, put, atomics)))
// Set pending bits for outstanding TileLink transaction // Set pending bits for outstanding TileLink transaction
val a_sel = UIntToOH(a_source, maxUncachedInFlight+mmioOffset) >> mmioOffset val a_sel = UIntToOH(a_source, maxUncachedInFlight+mmioOffset) >> mmioOffset
@ -392,7 +398,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
dataArb.io.in(1).bits.way_en := s2_victim_way dataArb.io.in(1).bits.way_en := s2_victim_way
dataArb.io.in(1).bits.wdata := tl_out.d.bits.data dataArb.io.in(1).bits.wdata := tl_out.d.bits.data
dataArb.io.in(1).bits.wordMask := ~UInt(0, rowBytes / wordBytes) dataArb.io.in(1).bits.wordMask := ~UInt(0, rowBytes / wordBytes)
dataArb.io.in(1).bits.byteMask := ~UInt(0, wordBytes) dataArb.io.in(1).bits.eccMask := ~UInt(0, wordBytes / eccBytes)
// tag updates on refill // tag updates on refill
metaWriteArb.io.in(1).valid := grantIsCached && d_done metaWriteArb.io.in(1).valid := grantIsCached && d_done
assert(!metaWriteArb.io.in(1).valid || metaWriteArb.io.in(1).ready) assert(!metaWriteArb.io.in(1).valid || metaWriteArb.io.in(1).ready)
@ -538,10 +544,10 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
io.cpu.resp.bits.store_data := pstore1_data io.cpu.resp.bits.store_data := pstore1_data
// AMOs // AMOs
if (usingAtomics) { if (usingRMW) {
val amoalu = Module(new AMOALU(xLen)) val amoalu = Module(new AMOALU(xLen))
amoalu.io.mask := pstore1_mask amoalu.io.mask := pstore1_mask
amoalu.io.cmd := pstore1_cmd amoalu.io.cmd := (if (usingAtomics) pstore1_cmd else M_XWR)
amoalu.io.lhs := s2_data_word amoalu.io.lhs := s2_data_word
amoalu.io.rhs := pstore1_data amoalu.io.rhs := pstore1_data
pstore1_storegen_data := amoalu.io.out pstore1_storegen_data := amoalu.io.out
@ -585,4 +591,10 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
def encodeData(x: UInt) = x.grouped(eccBits).map(dECC.encode(_)).asUInt def encodeData(x: UInt) = x.grouped(eccBits).map(dECC.encode(_)).asUInt
def dummyEncodeData(x: UInt) = x.grouped(eccBits).map(dECC.swizzle(_)).asUInt def dummyEncodeData(x: UInt) = x.grouped(eccBits).map(dECC.swizzle(_)).asUInt
def decodeData(x: UInt) = x.grouped(dECC.width(eccBits)).map(dECC.decode(_)) def decodeData(x: UInt) = x.grouped(dECC.width(eccBits)).map(dECC.decode(_))
def eccMask(byteMask: UInt) = byteMask.grouped(eccBytes).map(_.orR).asUInt
def eccByteMask(byteMask: UInt) = FillInterleaved(eccBytes, eccMask(byteMask))
def needsRead(req: HellaCacheReq) =
isRead(req.cmd) ||
(isWrite(req.cmd) && (req.cmd === M_PWR || mtSize(req.typ) < log2Ceil(eccBytes)))
} }