add ecc support to d$ data rams
i haven't injected errors yet; it may well be incorrect.
This commit is contained in:
parent
3f59e439ef
commit
f5c53ce35d
@ -51,9 +51,7 @@ class ALU(implicit conf: RocketConfiguration) extends Component
|
|||||||
val io = new ALUIO
|
val io = new ALUIO
|
||||||
|
|
||||||
// ADD, SUB
|
// ADD, SUB
|
||||||
val sub = isSub(io.fn)
|
val sum = io.in1 + Mux(isSub(io.fn), -io.in2, io.in2)
|
||||||
val adder_rhs = Mux(sub, ~io.in2, io.in2)
|
|
||||||
val sum = (io.in1 + adder_rhs + sub.toUFix)(63,0)
|
|
||||||
|
|
||||||
// SLT, SLTU
|
// SLT, SLTU
|
||||||
val less = Mux(io.in1(63) === io.in2(63), sum(63),
|
val less = Mux(io.in1(63) === io.in2(63), sum(63),
|
||||||
|
@ -8,8 +8,9 @@ import Util._
|
|||||||
|
|
||||||
case class DCacheConfig(sets: Int, ways: Int, co: CoherencePolicy,
|
case class DCacheConfig(sets: Int, ways: Int, co: CoherencePolicy,
|
||||||
nmshr: Int, nrpq: Int, nsdq: Int, ntlb: Int,
|
nmshr: Int, nrpq: Int, nsdq: Int, ntlb: Int,
|
||||||
reqtagbits: Int = -1, databits: Int = -1,
|
code: Code = new IdentityCode,
|
||||||
narrowRead: Boolean = true)
|
narrowRead: Boolean = true,
|
||||||
|
reqtagbits: Int = -1, databits: Int = -1)
|
||||||
{
|
{
|
||||||
require(isPow2(sets))
|
require(isPow2(sets))
|
||||||
require(isPow2(ways)) // TODO: relax this
|
require(isPow2(ways)) // TODO: relax this
|
||||||
@ -29,6 +30,12 @@ case class DCacheConfig(sets: Int, ways: Int, co: CoherencePolicy,
|
|||||||
def databytes = databits/8
|
def databytes = databits/8
|
||||||
def wordoffbits = log2Up(databytes)
|
def wordoffbits = log2Up(databytes)
|
||||||
def isNarrowRead = narrowRead && databits*ways % MEM_DATA_BITS == 0
|
def isNarrowRead = narrowRead && databits*ways % MEM_DATA_BITS == 0
|
||||||
|
val statebits = 2 // TODO: obtain from coherence policy
|
||||||
|
val metabits = statebits + tagbits
|
||||||
|
val encdatabits = code.width(databits)
|
||||||
|
val encmetabits = code.width(metabits)
|
||||||
|
val wordsperrow = MEM_DATA_BITS/databits
|
||||||
|
val bitsperrow = wordsperrow*encdatabits
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class ReplacementPolicy
|
abstract class ReplacementPolicy
|
||||||
@ -110,8 +117,8 @@ class DataReadReq(implicit conf: DCacheConfig) extends Bundle {
|
|||||||
class DataWriteReq(implicit conf: DCacheConfig) extends Bundle {
|
class DataWriteReq(implicit conf: DCacheConfig) extends Bundle {
|
||||||
val way_en = Bits(width = conf.ways)
|
val way_en = Bits(width = conf.ways)
|
||||||
val addr = Bits(width = conf.untagbits)
|
val addr = Bits(width = conf.untagbits)
|
||||||
val wmask = Bits(width = MEM_DATA_BITS/conf.databits)
|
val wmask = Bits(width = conf.wordsperrow)
|
||||||
val data = Bits(width = MEM_DATA_BITS)
|
val data = Bits(width = conf.bitsperrow)
|
||||||
|
|
||||||
override def clone = new DataWriteReq().asInstanceOf[this.type]
|
override def clone = new DataWriteReq().asInstanceOf[this.type]
|
||||||
}
|
}
|
||||||
@ -126,7 +133,7 @@ class WritebackReq(implicit conf: DCacheConfig) extends Bundle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class MetaData(implicit conf: DCacheConfig) extends Bundle {
|
class MetaData(implicit conf: DCacheConfig) extends Bundle {
|
||||||
val state = UFix(width = 2)
|
val state = UFix(width = conf.statebits)
|
||||||
val tag = Bits(width = conf.tagbits)
|
val tag = Bits(width = conf.tagbits)
|
||||||
|
|
||||||
override def clone = new MetaData().asInstanceOf[this.type]
|
override def clone = new MetaData().asInstanceOf[this.type]
|
||||||
@ -413,7 +420,7 @@ class WritebackUnit(implicit conf: DCacheConfig) extends Component {
|
|||||||
val probe = (new FIFOIO) { new WritebackReq() }.flip
|
val probe = (new FIFOIO) { new WritebackReq() }.flip
|
||||||
val meta_read = (new FIFOIO) { new MetaReadReq }
|
val meta_read = (new FIFOIO) { new MetaReadReq }
|
||||||
val data_req = (new FIFOIO) { new DataReadReq() }
|
val data_req = (new FIFOIO) { new DataReadReq() }
|
||||||
val data_resp = Bits(INPUT, MEM_DATA_BITS)
|
val data_resp = Bits(INPUT, conf.bitsperrow)
|
||||||
val mem_req = (new FIFOIO) { new TransactionInit }
|
val mem_req = (new FIFOIO) { new TransactionInit }
|
||||||
val mem_req_data = (new FIFOIO) { new TransactionInitData }
|
val mem_req_data = (new FIFOIO) { new TransactionInitData }
|
||||||
val probe_rep_data = (new FIFOIO) { new ProbeReplyData }
|
val probe_rep_data = (new FIFOIO) { new ProbeReplyData }
|
||||||
@ -430,7 +437,7 @@ class WritebackUnit(implicit conf: DCacheConfig) extends Component {
|
|||||||
when (valid) {
|
when (valid) {
|
||||||
r1_data_req_fired := false
|
r1_data_req_fired := false
|
||||||
r2_data_req_fired := r1_data_req_fired
|
r2_data_req_fired := r1_data_req_fired
|
||||||
when (io.data_req.fire()) {
|
when (io.data_req.fire() && io.meta_read.fire()) {
|
||||||
r1_data_req_fired := true
|
r1_data_req_fired := true
|
||||||
cnt := cnt + 1
|
cnt := cnt + 1
|
||||||
}
|
}
|
||||||
@ -467,7 +474,7 @@ class WritebackUnit(implicit conf: DCacheConfig) extends Component {
|
|||||||
val fire = valid && cnt < UFix(REFILL_CYCLES)
|
val fire = valid && cnt < UFix(REFILL_CYCLES)
|
||||||
io.req.ready := !valid && !io.probe.valid
|
io.req.ready := !valid && !io.probe.valid
|
||||||
io.probe.ready := !valid
|
io.probe.ready := !valid
|
||||||
io.data_req.valid := fire && io.meta_read.ready
|
io.data_req.valid := fire
|
||||||
io.data_req.bits.way_en := req.way_en
|
io.data_req.bits.way_en := req.way_en
|
||||||
io.data_req.bits.addr := Cat(req.idx, cnt(log2Up(REFILL_CYCLES)-1,0)) << conf.ramoffbits
|
io.data_req.bits.addr := Cat(req.idx, cnt(log2Up(REFILL_CYCLES)-1,0)) << conf.ramoffbits
|
||||||
|
|
||||||
@ -480,7 +487,7 @@ class WritebackUnit(implicit conf: DCacheConfig) extends Component {
|
|||||||
io.probe_rep_data.valid := r2_data_req_fired && is_probe
|
io.probe_rep_data.valid := r2_data_req_fired && is_probe
|
||||||
io.probe_rep_data.bits.data := io.data_resp
|
io.probe_rep_data.bits.data := io.data_resp
|
||||||
|
|
||||||
io.meta_read.valid := fire && io.data_req.ready
|
io.meta_read.valid := fire
|
||||||
io.meta_read.bits.addr := io.mem_req.bits.addr << conf.offbits
|
io.meta_read.bits.addr := io.mem_req.bits.addr << conf.offbits
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,32 +601,31 @@ class DataArray(implicit conf: DCacheConfig) extends Component {
|
|||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val read = new FIFOIO()(new DataReadReq).flip
|
val read = new FIFOIO()(new DataReadReq).flip
|
||||||
val write = new FIFOIO()(new DataWriteReq).flip
|
val write = new FIFOIO()(new DataWriteReq).flip
|
||||||
val resp = Vec(conf.ways){ Bits(OUTPUT, MEM_DATA_BITS) }
|
val resp = Vec(conf.ways){ Bits(OUTPUT, conf.bitsperrow) }
|
||||||
}
|
}
|
||||||
|
|
||||||
val waddr = io.write.bits.addr >> conf.ramoffbits
|
val waddr = io.write.bits.addr >> conf.ramoffbits
|
||||||
val raddr = io.read.bits.addr >> conf.ramoffbits
|
val raddr = io.read.bits.addr >> conf.ramoffbits
|
||||||
|
|
||||||
if (conf.isNarrowRead) {
|
if (conf.isNarrowRead) {
|
||||||
val waysPerMem = MEM_DATA_BITS/conf.databits
|
for (w <- 0 until conf.ways by conf.wordsperrow) {
|
||||||
for (w <- 0 until conf.ways by waysPerMem) {
|
val wway_en = io.write.bits.way_en(w+conf.wordsperrow-1,w)
|
||||||
val wway_en = io.write.bits.way_en(w+waysPerMem-1,w)
|
val rway_en = io.read.bits.way_en(w+conf.wordsperrow-1,w)
|
||||||
val rway_en = io.read.bits.way_en(w+waysPerMem-1,w)
|
val resp = Vec(conf.wordsperrow){Reg{Bits(width = conf.bitsperrow)}}
|
||||||
val resp = Vec(MEM_DATA_BITS/conf.databits){Reg{Bits(width = MEM_DATA_BITS)}}
|
|
||||||
val r_raddr = RegEn(io.read.bits.addr, io.read.valid)
|
val r_raddr = RegEn(io.read.bits.addr, io.read.valid)
|
||||||
for (p <- 0 until resp.size) {
|
for (p <- 0 until resp.size) {
|
||||||
val array = Mem(conf.sets*REFILL_CYCLES, seqRead = true){ Bits(width=MEM_DATA_BITS) }
|
val array = Mem(conf.sets*REFILL_CYCLES, seqRead = true){ Bits(width=conf.bitsperrow) }
|
||||||
when (wway_en.orR && io.write.valid && io.write.bits.wmask(p)) {
|
when (wway_en.orR && io.write.valid && io.write.bits.wmask(p)) {
|
||||||
val data = Fill(waysPerMem, io.write.bits.data(conf.databits*(p+1)-1,conf.databits*p))
|
val data = Fill(conf.wordsperrow, io.write.bits.data(conf.encdatabits*(p+1)-1,conf.encdatabits*p))
|
||||||
val mask = FillInterleaved(conf.databits, wway_en)
|
val mask = FillInterleaved(conf.encdatabits, wway_en)
|
||||||
array.write(waddr, data, mask)
|
array.write(waddr, data, mask)
|
||||||
}
|
}
|
||||||
when (rway_en.orR && io.read.valid) {
|
when (rway_en.orR && io.read.valid) {
|
||||||
resp(p) := array(raddr)
|
resp(p) := array(raddr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (dw <- 0 until waysPerMem) {
|
for (dw <- 0 until conf.wordsperrow) {
|
||||||
val r = AVec(resp.map(_(conf.databits*(dw+1)-1,conf.databits*dw)))
|
val r = AVec(resp.map(_(conf.encdatabits*(dw+1)-1,conf.encdatabits*dw)))
|
||||||
val resp_mux =
|
val resp_mux =
|
||||||
if (r.size == 1) r
|
if (r.size == 1) r
|
||||||
else AVec(r(r_raddr(conf.ramoffbits-1,conf.wordoffbits)), r.tail:_*)
|
else AVec(r(r_raddr(conf.ramoffbits-1,conf.wordoffbits)), r.tail:_*)
|
||||||
@ -627,10 +633,10 @@ class DataArray(implicit conf: DCacheConfig) extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val wmask = FillInterleaved(conf.databits, io.write.bits.wmask)
|
val wmask = FillInterleaved(conf.encdatabits, io.write.bits.wmask)
|
||||||
for (w <- 0 until conf.ways) {
|
for (w <- 0 until conf.ways) {
|
||||||
val rdata = Reg() { Bits() }
|
val rdata = Reg() { Bits() }
|
||||||
val array = Mem(conf.sets*REFILL_CYCLES, seqRead = true){ Bits(width=MEM_DATA_BITS) }
|
val array = Mem(conf.sets*REFILL_CYCLES, seqRead = true){ Bits(width=conf.bitsperrow) }
|
||||||
when (io.write.bits.way_en(w) && io.write.valid) {
|
when (io.write.bits.way_en(w) && io.write.valid) {
|
||||||
array.write(waddr, io.write.bits.data, wmask)
|
array.write(waddr, io.write.bits.data, wmask)
|
||||||
}
|
}
|
||||||
@ -752,12 +758,14 @@ class HellaCache(implicit conf: DCacheConfig) extends Component {
|
|||||||
val s2_valid = Reg(s1_valid_masked, resetVal = Bool(false))
|
val s2_valid = Reg(s1_valid_masked, resetVal = Bool(false))
|
||||||
val s2_req = Reg{io.cpu.req.bits.clone}
|
val s2_req = Reg{io.cpu.req.bits.clone}
|
||||||
val s2_replay = Reg(s1_replay, resetVal = Bool(false))
|
val s2_replay = Reg(s1_replay, resetVal = Bool(false))
|
||||||
|
val s2_recycle = Bool()
|
||||||
val s2_valid_masked = Bool()
|
val s2_valid_masked = Bool()
|
||||||
|
|
||||||
val s3_valid = Reg(resetVal = Bool(false))
|
val s3_valid = Reg(resetVal = Bool(false))
|
||||||
val s3_req = Reg{io.cpu.req.bits.clone}
|
val s3_req = Reg{io.cpu.req.bits.clone}
|
||||||
val s3_way = Reg{Bits()}
|
val s3_way = Reg{Bits()}
|
||||||
|
|
||||||
|
val s1_recycled = RegEn(s2_recycle, s1_clk_en)
|
||||||
val s1_read = isRead(s1_req.cmd)
|
val s1_read = isRead(s1_req.cmd)
|
||||||
val s1_write = isWrite(s1_req.cmd)
|
val s1_write = isWrite(s1_req.cmd)
|
||||||
val s1_readwrite = s1_read || s1_write || isPrefetch(s1_req.cmd)
|
val s1_readwrite = s1_read || s1_write || isPrefetch(s1_req.cmd)
|
||||||
@ -785,6 +793,9 @@ class HellaCache(implicit conf: DCacheConfig) extends Component {
|
|||||||
when (mshr.io.replay.valid) {
|
when (mshr.io.replay.valid) {
|
||||||
s1_req := mshr.io.replay.bits
|
s1_req := mshr.io.replay.bits
|
||||||
}
|
}
|
||||||
|
when (s2_recycle) {
|
||||||
|
s1_req := s2_req
|
||||||
|
}
|
||||||
val s1_addr = Cat(dtlb.io.resp.ppn, s1_req.addr(conf.pgidxbits-1,0))
|
val s1_addr = Cat(dtlb.io.resp.ppn, s1_req.addr(conf.pgidxbits-1,0))
|
||||||
|
|
||||||
when (s1_clk_en) {
|
when (s1_clk_en) {
|
||||||
@ -795,6 +806,7 @@ class HellaCache(implicit conf: DCacheConfig) extends Component {
|
|||||||
when (s1_write) {
|
when (s1_write) {
|
||||||
s2_req.data := Mux(s1_replay, mshr.io.replay.bits.data, io.cpu.req.bits.data)
|
s2_req.data := Mux(s1_replay, mshr.io.replay.bits.data, io.cpu.req.bits.data)
|
||||||
}
|
}
|
||||||
|
when (s1_recycled) { s2_req.data := s1_req.data }
|
||||||
}
|
}
|
||||||
|
|
||||||
val misaligned =
|
val misaligned =
|
||||||
@ -809,29 +821,41 @@ class HellaCache(implicit conf: DCacheConfig) extends Component {
|
|||||||
|
|
||||||
// tags
|
// tags
|
||||||
val meta = new MetaDataArray
|
val meta = new MetaDataArray
|
||||||
val metaReadArb = (new Arbiter(4)) { new MetaReadReq }
|
val metaReadArb = (new Arbiter(5)) { new MetaReadReq }
|
||||||
val metaWriteArb = (new Arbiter(2)) { new MetaWriteReq }
|
val metaWriteArb = (new Arbiter(2)) { new MetaWriteReq }
|
||||||
metaReadArb.io.out <> meta.io.read
|
metaReadArb.io.out <> meta.io.read
|
||||||
metaWriteArb.io.out <> meta.io.write
|
metaWriteArb.io.out <> meta.io.write
|
||||||
|
|
||||||
// data
|
// data
|
||||||
val data = new DataArray
|
val data = new DataArray
|
||||||
val readArb = new Arbiter(3)(new DataReadReq)
|
val readArb = new Arbiter(4)(new DataReadReq)
|
||||||
val writeArb = new Arbiter(2)(new DataWriteReq)
|
|
||||||
readArb.io.out.ready := !io.mem.xact_rep.valid || io.mem.xact_rep.ready // insert bubble if refill gets blocked
|
readArb.io.out.ready := !io.mem.xact_rep.valid || io.mem.xact_rep.ready // insert bubble if refill gets blocked
|
||||||
readArb.io.out <> data.io.read
|
readArb.io.out <> data.io.read
|
||||||
writeArb.io.out <> data.io.write
|
|
||||||
|
val writeArb = new Arbiter(2)(new DataWriteReq)
|
||||||
|
data.io.write.valid := writeArb.io.out.valid
|
||||||
|
writeArb.io.out.ready := data.io.write.ready
|
||||||
|
data.io.write.bits := writeArb.io.out.bits
|
||||||
|
val wdata_encoded = (0 until conf.wordsperrow).map(i => conf.code.encode(writeArb.io.out.bits.data(conf.databits*(i+1)-1,conf.databits*i)))
|
||||||
|
data.io.write.bits.data := AVec(wdata_encoded).toBits
|
||||||
|
|
||||||
// tag read for new requests
|
// tag read for new requests
|
||||||
metaReadArb.io.in(3).valid := io.cpu.req.valid
|
metaReadArb.io.in(4).valid := io.cpu.req.valid
|
||||||
metaReadArb.io.in(3).bits.addr := io.cpu.req.bits.addr
|
metaReadArb.io.in(4).bits.addr := io.cpu.req.bits.addr
|
||||||
when (!metaReadArb.io.in(3).ready) { io.cpu.req.ready := Bool(false) }
|
when (!metaReadArb.io.in(4).ready) { io.cpu.req.ready := Bool(false) }
|
||||||
|
|
||||||
// data read for new requests
|
// data read for new requests
|
||||||
readArb.io.in(2).bits.addr := io.cpu.req.bits.addr
|
readArb.io.in(3).bits.addr := io.cpu.req.bits.addr
|
||||||
readArb.io.in(2).valid := io.cpu.req.valid
|
readArb.io.in(3).valid := io.cpu.req.valid
|
||||||
readArb.io.in(2).bits.way_en := Fix(-1)
|
readArb.io.in(3).bits.way_en := Fix(-1)
|
||||||
when (!readArb.io.in(2).ready) { io.cpu.req.ready := Bool(false) }
|
when (!readArb.io.in(3).ready) { io.cpu.req.ready := Bool(false) }
|
||||||
|
|
||||||
|
// recycled requests
|
||||||
|
metaReadArb.io.in(0).valid := s2_recycle
|
||||||
|
metaReadArb.io.in(0).bits.addr := s2_req.addr
|
||||||
|
readArb.io.in(0).valid := s2_recycle
|
||||||
|
readArb.io.in(0).bits.addr := s2_req.addr
|
||||||
|
readArb.io.in(0).bits.way_en := Fix(-1)
|
||||||
|
|
||||||
// tag check and way muxing
|
// tag check and way muxing
|
||||||
def wayMap[T <: Data](f: Int => T)(gen: => T) = Vec((0 until conf.ways).map(i => f(i))){gen}
|
def wayMap[T <: Data](f: Int => T)(gen: => T) = Vec((0 until conf.ways).map(i => f(i))){gen}
|
||||||
@ -844,30 +868,35 @@ class HellaCache(implicit conf: DCacheConfig) extends Component {
|
|||||||
val s2_hit_state = Mux1H(s2_tag_match_way, wayMap((w: Int) => RegEn(meta.io.resp(w).state, s1_clk_en)){Bits()})
|
val s2_hit_state = Mux1H(s2_tag_match_way, wayMap((w: Int) => RegEn(meta.io.resp(w).state, s1_clk_en)){Bits()})
|
||||||
val s2_hit = s2_tag_match && conf.co.isHit(s2_req.cmd, s2_hit_state) && s2_hit_state === conf.co.newStateOnHit(s2_req.cmd, s2_hit_state)
|
val s2_hit = s2_tag_match && conf.co.isHit(s2_req.cmd, s2_hit_state) && s2_hit_state === conf.co.newStateOnHit(s2_req.cmd, s2_hit_state)
|
||||||
|
|
||||||
val s2_data = Vec(conf.ways){Bits(width = MEM_DATA_BITS)}
|
val s2_data = Vec(conf.ways){Bits(width = conf.bitsperrow)}
|
||||||
for (w <- 0 until conf.ways) {
|
for (w <- 0 until conf.ways) {
|
||||||
val regs = Vec(MEM_DATA_BITS/conf.databits){Reg{Bits(width = conf.databits)}}
|
val regs = Vec(conf.wordsperrow){Reg{Bits(width = conf.encdatabits)}}
|
||||||
val en1 = s1_clk_en && s1_tag_eq_way(w)
|
val en1 = s1_clk_en && s1_tag_eq_way(w)
|
||||||
for (i <- 0 until regs.size) {
|
for (i <- 0 until regs.size) {
|
||||||
val en = en1 && (Bool(i == 0 || !conf.isNarrowRead) || s1_writeback)
|
val en = en1 && (Bool(i == 0 || !conf.isNarrowRead) || s1_writeback)
|
||||||
when (en) { regs(i) := data.io.resp(w) >> conf.databits*i }
|
when (en) { regs(i) := data.io.resp(w) >> conf.encdatabits*i }
|
||||||
}
|
}
|
||||||
s2_data(w) := Cat(regs.last, regs.init.reverse:_*)
|
s2_data(w) := regs.toBits
|
||||||
}
|
}
|
||||||
val data_resp_mux = Mux1H(s2_tag_match_way, s2_data)
|
val s2_data_muxed = Mux1H(s2_tag_match_way, s2_data)
|
||||||
|
val s2_data_decoded = (0 until conf.wordsperrow).map(i => conf.code.decode(s2_data_muxed(conf.encdatabits*(i+1)-1,conf.encdatabits*i)))
|
||||||
|
val s2_data_corrected = AVec(s2_data_decoded.map(_.corrected)).toBits
|
||||||
|
val s2_data_uncorrected = AVec(s2_data_decoded.map(_.uncorrected)).toBits
|
||||||
|
val s2_word_idx = if (conf.isNarrowRead) UFix(0) else s2_req.addr(log2Up(conf.wordsperrow*conf.databytes)-1,3)
|
||||||
|
val s2_data_correctable = AVec(s2_data_decoded.map(_.correctable)).toBits()(s2_word_idx)
|
||||||
|
|
||||||
// store/amo hits
|
// store/amo hits
|
||||||
s3_valid := (s2_valid_masked && s2_hit || s2_replay) && isWrite(s2_req.cmd)
|
s3_valid := (s2_valid_masked && s2_hit || s2_replay) && isWrite(s2_req.cmd)
|
||||||
val amoalu = new AMOALU
|
val amoalu = new AMOALU
|
||||||
when ((s2_valid || s2_replay) && isWrite(s2_req.cmd)) {
|
when ((s2_valid || s2_replay) && (isWrite(s2_req.cmd) || s2_data_correctable)) {
|
||||||
s3_req := s2_req
|
s3_req := s2_req
|
||||||
s3_req.data := amoalu.io.out
|
s3_req.data := Mux(s2_data_correctable, s2_data_corrected, amoalu.io.out)
|
||||||
s3_way := s2_tag_match_way
|
s3_way := s2_tag_match_way
|
||||||
}
|
}
|
||||||
|
|
||||||
writeArb.io.in(0).bits.addr := s3_req.addr
|
writeArb.io.in(0).bits.addr := s3_req.addr
|
||||||
writeArb.io.in(0).bits.wmask := UFix(1) << s3_req.addr(conf.ramoffbits-1,offsetlsb).toUFix
|
writeArb.io.in(0).bits.wmask := UFix(1) << s3_req.addr(conf.ramoffbits-1,offsetlsb).toUFix
|
||||||
writeArb.io.in(0).bits.data := Fill(MEM_DATA_BITS/conf.databits, s3_req.data)
|
writeArb.io.in(0).bits.data := Fill(conf.wordsperrow, s3_req.data)
|
||||||
writeArb.io.in(0).valid := s3_valid
|
writeArb.io.in(0).valid := s3_valid
|
||||||
writeArb.io.in(0).bits.way_en := s3_way
|
writeArb.io.in(0).bits.way_en := s3_way
|
||||||
|
|
||||||
@ -875,15 +904,13 @@ class HellaCache(implicit conf: DCacheConfig) extends Component {
|
|||||||
val replacer = new RandomReplacement
|
val replacer = new RandomReplacement
|
||||||
val s1_replaced_way_en = UFixToOH(replacer.way)
|
val s1_replaced_way_en = UFixToOH(replacer.way)
|
||||||
val s2_replaced_way_en = UFixToOH(RegEn(replacer.way, s1_clk_en))
|
val s2_replaced_way_en = UFixToOH(RegEn(replacer.way, s1_clk_en))
|
||||||
val s2_repl_state = Mux1H(s2_replaced_way_en, wayMap((w: Int) => RegEn(meta.io.resp(w).state, s1_clk_en && s1_replaced_way_en(w))){Bits()})
|
val s2_repl_meta = Mux1H(s2_replaced_way_en, wayMap((w: Int) => RegEn(meta.io.resp(w), s1_clk_en && s1_replaced_way_en(w))){new MetaData})
|
||||||
val s2_repl_tag = Mux1H(s2_replaced_way_en, wayMap((w: Int) => RegEn(meta.io.resp(w).tag, s1_clk_en && s1_replaced_way_en(w))){Bits()})
|
|
||||||
|
|
||||||
// miss handling
|
// miss handling
|
||||||
mshr.io.req.valid := s2_valid_masked && !s2_hit && (isPrefetch(s2_req.cmd) || isRead(s2_req.cmd) || isWrite(s2_req.cmd))
|
mshr.io.req.valid := s2_valid_masked && !s2_hit && (isPrefetch(s2_req.cmd) || isRead(s2_req.cmd) || isWrite(s2_req.cmd))
|
||||||
mshr.io.req.bits := s2_req
|
mshr.io.req.bits := s2_req
|
||||||
mshr.io.req.bits.tag_match := s2_tag_match
|
mshr.io.req.bits.tag_match := s2_tag_match
|
||||||
mshr.io.req.bits.old_meta.state := s2_repl_state
|
mshr.io.req.bits.old_meta := s2_repl_meta
|
||||||
mshr.io.req.bits.old_meta.tag := s2_repl_tag
|
|
||||||
mshr.io.req.bits.way_en := Mux(s2_tag_match, s2_tag_match_way, s2_replaced_way_en)
|
mshr.io.req.bits.way_en := Mux(s2_tag_match, s2_tag_match_way, s2_replaced_way_en)
|
||||||
mshr.io.req.bits.data := s2_req.data
|
mshr.io.req.bits.data := s2_req.data
|
||||||
|
|
||||||
@ -895,12 +922,12 @@ class HellaCache(implicit conf: DCacheConfig) extends Component {
|
|||||||
when (mshr.io.req.fire()) { replacer.miss }
|
when (mshr.io.req.fire()) { replacer.miss }
|
||||||
|
|
||||||
// replays
|
// replays
|
||||||
readArb.io.in(0).valid := mshr.io.replay.valid
|
readArb.io.in(1).valid := mshr.io.replay.valid
|
||||||
readArb.io.in(0).bits := mshr.io.replay.bits
|
readArb.io.in(1).bits := mshr.io.replay.bits
|
||||||
readArb.io.in(0).bits.way_en := Fix(-1)
|
readArb.io.in(1).bits.way_en := Fix(-1)
|
||||||
mshr.io.replay.ready := Bool(true)
|
mshr.io.replay.ready := readArb.io.in(1).ready
|
||||||
s1_replay := mshr.io.replay.fire()
|
s1_replay := mshr.io.replay.valid && readArb.io.in(1).ready
|
||||||
metaReadArb.io.in(0) <> mshr.io.meta_read
|
metaReadArb.io.in(1) <> mshr.io.meta_read
|
||||||
metaWriteArb.io.in(0) <> mshr.io.meta_write
|
metaWriteArb.io.in(0) <> mshr.io.meta_write
|
||||||
|
|
||||||
// probes
|
// probes
|
||||||
@ -910,7 +937,7 @@ class HellaCache(implicit conf: DCacheConfig) extends Component {
|
|||||||
prober.io.wb_req <> wb.io.probe
|
prober.io.wb_req <> wb.io.probe
|
||||||
prober.io.way_en := s2_tag_match_way
|
prober.io.way_en := s2_tag_match_way
|
||||||
prober.io.line_state := s2_hit_state
|
prober.io.line_state := s2_hit_state
|
||||||
prober.io.meta_read <> metaReadArb.io.in(1)
|
prober.io.meta_read <> metaReadArb.io.in(2)
|
||||||
prober.io.meta_write <> metaWriteArb.io.in(1)
|
prober.io.meta_write <> metaWriteArb.io.in(1)
|
||||||
|
|
||||||
// refills
|
// refills
|
||||||
@ -923,9 +950,9 @@ class HellaCache(implicit conf: DCacheConfig) extends Component {
|
|||||||
|
|
||||||
// writebacks
|
// writebacks
|
||||||
wb.io.req <> mshr.io.wb_req
|
wb.io.req <> mshr.io.wb_req
|
||||||
wb.io.meta_read <> metaReadArb.io.in(2)
|
wb.io.meta_read <> metaReadArb.io.in(3)
|
||||||
wb.io.data_req <> readArb.io.in(1)
|
wb.io.data_req <> readArb.io.in(2)
|
||||||
wb.io.data_resp := data_resp_mux
|
wb.io.data_resp := s2_data_corrected
|
||||||
wb.io.probe_rep_data <> io.mem.probe_rep_data
|
wb.io.probe_rep_data <> io.mem.probe_rep_data
|
||||||
|
|
||||||
// store->load bypassing
|
// store->load bypassing
|
||||||
@ -947,9 +974,7 @@ class HellaCache(implicit conf: DCacheConfig) extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// load data subword mux/sign extension
|
// load data subword mux/sign extension
|
||||||
val s2_data_word_prebypass =
|
val s2_data_word_prebypass = s2_data_uncorrected >> Cat(s2_word_idx, Bits(0,log2Up(conf.databits)))
|
||||||
if (conf.isNarrowRead) data_resp_mux(conf.databits-1,0)
|
|
||||||
else data_resp_mux >> Cat(s2_req.addr(log2Up(MEM_DATA_BITS/8)-1,3), Bits(0,log2Up(conf.databits)))
|
|
||||||
val s2_data_word = Mux(s2_store_bypass, s2_store_bypass_data, s2_data_word_prebypass)
|
val s2_data_word = Mux(s2_store_bypass, s2_store_bypass_data, s2_data_word_prebypass)
|
||||||
val loadgen = new LoadGen(s2_req.typ, s2_req.addr, s2_data_word)
|
val loadgen = new LoadGen(s2_req.typ, s2_req.addr, s2_data_word)
|
||||||
|
|
||||||
@ -968,6 +993,11 @@ class HellaCache(implicit conf: DCacheConfig) extends Component {
|
|||||||
val s2_nack = s2_nack_hit || s2_nack_victim || s2_nack_miss || s2_nack_fence
|
val s2_nack = s2_nack_hit || s2_nack_victim || s2_nack_miss || s2_nack_fence
|
||||||
s2_valid_masked := s2_valid && !s2_nack
|
s2_valid_masked := s2_valid && !s2_nack
|
||||||
|
|
||||||
|
val s2_recycle_ecc = (s2_valid || s2_replay) && s2_hit && s2_data_correctable
|
||||||
|
val s2_recycle_next = Reg(resetVal = Bool(false))
|
||||||
|
when (s1_valid || s1_replay) { s2_recycle_next := (s1_valid || s1_replay) && s2_recycle_ecc }
|
||||||
|
s2_recycle := s2_recycle_ecc || s2_recycle_next
|
||||||
|
|
||||||
// after a nack, block until nack condition resolves to save energy
|
// after a nack, block until nack condition resolves to save energy
|
||||||
val block_fence = Reg(resetVal = Bool(false))
|
val block_fence = Reg(resetVal = Bool(false))
|
||||||
block_fence := (s2_valid && s2_req.cmd === M_FENCE || block_fence) && !mshr.io.fence_rdy
|
block_fence := (s2_valid && s2_req.cmd === M_FENCE || block_fence) && !mshr.io.fence_rdy
|
||||||
@ -978,7 +1008,7 @@ class HellaCache(implicit conf: DCacheConfig) extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val s2_read = isRead(s2_req.cmd)
|
val s2_read = isRead(s2_req.cmd)
|
||||||
io.cpu.resp.valid := s2_read && (s2_replay || s2_valid_masked && s2_hit)
|
io.cpu.resp.valid := s2_read && (s2_replay || s2_valid_masked && s2_hit) && !s2_data_correctable
|
||||||
io.cpu.resp.bits.nack := s2_valid && s2_nack
|
io.cpu.resp.bits.nack := s2_valid && s2_nack
|
||||||
io.cpu.resp.bits := s2_req
|
io.cpu.resp.bits := s2_req
|
||||||
io.cpu.resp.bits.replay := s2_replay && s2_read
|
io.cpu.resp.bits.replay := s2_replay && s2_read
|
||||||
|
@ -17,6 +17,11 @@ object AVec
|
|||||||
def apply[T <: Data](elts: Seq[T]): Vec[T] = Vec(elts) { elts.head.clone }
|
def apply[T <: Data](elts: Seq[T]): Vec[T] = Vec(elts) { elts.head.clone }
|
||||||
def apply[T <: Data](elts: Vec[T]): Vec[T] = apply(elts.toSeq)
|
def apply[T <: Data](elts: Vec[T]): Vec[T] = apply(elts.toSeq)
|
||||||
def apply[T <: Data](elt0: T, elts: T*): Vec[T] = apply(elt0 :: elts.toList)
|
def apply[T <: Data](elt0: T, elts: T*): Vec[T] = apply(elt0 :: elts.toList)
|
||||||
|
|
||||||
|
def tabulate[T <: Data](n: Int)(f: Int => T): Vec[T] =
|
||||||
|
apply((0 until n).map(i => f(i)))
|
||||||
|
def tabulate[T <: Data](n1: Int, n2: Int)(f: (Int, Int) => T): Vec[Vec[T]] =
|
||||||
|
tabulate(n1)(i1 => tabulate(n2)(f(i1, _)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// a counter that clock gates most of its MSBs using the LSB carry-out
|
// a counter that clock gates most of its MSBs using the LSB carry-out
|
||||||
|
Loading…
Reference in New Issue
Block a user