Support eccBytes > 1
This commit is contained in:
parent
8e4be40efc
commit
b9a934ae28
@ -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)))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user