refactor Metadata, clean and expand coherence API
This commit is contained in:
parent
8bc1c33540
commit
dab675b231
@ -80,7 +80,7 @@ class LoadGen(typ: Bits, addr: Bits, dat: Bits, zero: Bool)
|
|||||||
|
|
||||||
class MSHRReq(implicit val cacheconf: DCacheConfig) extends HellaCacheReq {
|
class MSHRReq(implicit val cacheconf: DCacheConfig) extends HellaCacheReq {
|
||||||
val tag_match = Bool()
|
val tag_match = Bool()
|
||||||
val old_meta = new L1MetaData
|
val old_meta = new L1Metadata
|
||||||
val way_en = Bits(width = cacheconf.ways)
|
val way_en = Bits(width = cacheconf.ways)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,20 +98,23 @@ class DataWriteReq(implicit conf: DCacheConfig) extends DataReadReq {
|
|||||||
val data = Bits(width = conf.encrowbits)
|
val data = Bits(width = conf.encrowbits)
|
||||||
}
|
}
|
||||||
|
|
||||||
object L1MetaData {
|
class L1MetaReadReq(implicit conf: DCacheConfig) extends MetaReadReq {
|
||||||
def apply(tag: Bits, state: UInt)(implicit conf: DCacheConfig) = {
|
val tag = Bits(width = conf.tagbits)
|
||||||
val meta = new L1MetaData
|
}
|
||||||
meta.state := state
|
|
||||||
|
class L1MetaWriteReq(implicit conf: DCacheConfig) extends
|
||||||
|
MetaWriteReq[L1Metadata](new L1Metadata)
|
||||||
|
|
||||||
|
object L1Metadata {
|
||||||
|
def apply(tag: Bits, coh: ClientMetadata)(implicit conf: DCacheConfig) = {
|
||||||
|
val meta = new L1Metadata
|
||||||
meta.tag := tag
|
meta.tag := tag
|
||||||
|
meta.coh := coh
|
||||||
meta
|
meta
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class L1MetaData(implicit val conf: DCacheConfig) extends MetaData {
|
class L1Metadata(implicit val conf: DCacheConfig) extends Metadata {
|
||||||
val state = UInt(width = conf.statebits)
|
val coh = conf.tl.co.clientMetadataOnFlush.clone
|
||||||
}
|
|
||||||
|
|
||||||
class L1MetaReadReq(implicit conf: DCacheConfig) extends MetaReadReq {
|
|
||||||
val tag = Bits(width = conf.tagbits)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class InternalProbe(implicit conf: TileLinkConfiguration) extends Probe()(conf)
|
class InternalProbe(implicit conf: TileLinkConfiguration) extends Probe()(conf)
|
||||||
@ -142,7 +145,7 @@ class MSHR(id: Int)(implicit conf: DCacheConfig) extends Module {
|
|||||||
val mem_req = Decoupled(new Acquire)
|
val mem_req = Decoupled(new Acquire)
|
||||||
val mem_resp = new DataWriteReq().asOutput
|
val mem_resp = new DataWriteReq().asOutput
|
||||||
val meta_read = Decoupled(new L1MetaReadReq)
|
val meta_read = Decoupled(new L1MetaReadReq)
|
||||||
val meta_write = Decoupled(new MetaWriteReq(new L1MetaData))
|
val meta_write = Decoupled(new L1MetaWriteReq)
|
||||||
val replay = Decoupled(new Replay)
|
val replay = Decoupled(new Replay)
|
||||||
val mem_grant = Valid(new LogicalNetworkIO(new Grant)).flip
|
val mem_grant = Valid(new LogicalNetworkIO(new Grant)).flip
|
||||||
val mem_finish = Decoupled(new LogicalNetworkIO(new Finish))
|
val mem_finish = Decoupled(new LogicalNetworkIO(new Finish))
|
||||||
@ -155,7 +158,7 @@ class MSHR(id: Int)(implicit conf: DCacheConfig) extends Module {
|
|||||||
|
|
||||||
val acquire_type = Reg(UInt())
|
val acquire_type = Reg(UInt())
|
||||||
val release_type = Reg(UInt())
|
val release_type = Reg(UInt())
|
||||||
val line_state = Reg(UInt())
|
val line_state = Reg(new ClientMetadata()(tl.co))
|
||||||
val refill_count = Reg(UInt(width = log2Up(conf.refillcycles))) // TODO: zero-width wire
|
val refill_count = Reg(UInt(width = log2Up(conf.refillcycles))) // TODO: zero-width wire
|
||||||
val req = Reg(new MSHRReq())
|
val req = Reg(new MSHRReq())
|
||||||
|
|
||||||
@ -169,6 +172,10 @@ class MSHR(id: Int)(implicit conf: DCacheConfig) extends Module {
|
|||||||
val refill_done = reply && (if(conf.refillcycles > 1) refill_count.andR else Bool(true))
|
val refill_done = reply && (if(conf.refillcycles > 1) refill_count.andR else Bool(true))
|
||||||
val wb_done = reply && (state === s_wb_resp)
|
val wb_done = reply && (state === s_wb_resp)
|
||||||
|
|
||||||
|
val meta_on_flush = tl.co.clientMetadataOnFlush
|
||||||
|
val meta_on_grant = tl.co.clientMetadataOnGrant(io.mem_grant.bits.payload, io.mem_req.bits)
|
||||||
|
val meta_on_hit = tl.co.clientMetadataOnHit(req_cmd, io.req_bits.old_meta.coh)
|
||||||
|
|
||||||
val rpq = Module(new Queue(new Replay, conf.nrpq))
|
val rpq = Module(new Queue(new Replay, conf.nrpq))
|
||||||
rpq.io.enq.valid := (io.req_pri_val && io.req_pri_rdy || io.req_sec_val && sec_rdy) && !isPrefetch(req_cmd)
|
rpq.io.enq.valid := (io.req_pri_val && io.req_pri_rdy || io.req_sec_val && sec_rdy) && !isPrefetch(req_cmd)
|
||||||
rpq.io.enq.bits := io.req_bits
|
rpq.io.enq.bits := io.req_bits
|
||||||
@ -189,7 +196,7 @@ class MSHR(id: Int)(implicit conf: DCacheConfig) extends Module {
|
|||||||
when (refill_done) { state := s_meta_write_req }
|
when (refill_done) { state := s_meta_write_req }
|
||||||
when (reply) {
|
when (reply) {
|
||||||
if(conf.refillcycles > 1) refill_count := refill_count + UInt(1)
|
if(conf.refillcycles > 1) refill_count := refill_count + UInt(1)
|
||||||
line_state := tl.co.newStateOnGrant(io.mem_grant.bits.payload, io.mem_req.bits)
|
line_state := meta_on_grant
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
when (io.mem_req.fire()) { // s_refill_req
|
when (io.mem_req.fire()) { // s_refill_req
|
||||||
@ -206,24 +213,24 @@ class MSHR(id: Int)(implicit conf: DCacheConfig) extends Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
when (io.req_sec_val && io.req_sec_rdy) { // s_wb_req, s_wb_resp, s_refill_req
|
when (io.req_sec_val && io.req_sec_rdy) { // s_wb_req, s_wb_resp, s_refill_req
|
||||||
acquire_type := tl.co.getAcquireTypeOnSecondaryMiss(req_cmd, tl.co.newStateOnFlush(), io.mem_req.bits)
|
acquire_type := tl.co.getAcquireTypeOnSecondaryMiss(req_cmd, meta_on_flush, io.mem_req.bits)
|
||||||
}
|
}
|
||||||
when (io.req_pri_val && io.req_pri_rdy) {
|
when (io.req_pri_val && io.req_pri_rdy) {
|
||||||
line_state := tl.co.newStateOnFlush()
|
line_state := meta_on_flush
|
||||||
refill_count := UInt(0)
|
refill_count := UInt(0)
|
||||||
acquire_type := tl.co.getAcquireTypeOnPrimaryMiss(req_cmd, tl.co.newStateOnFlush())
|
acquire_type := tl.co.getAcquireTypeOnPrimaryMiss(req_cmd, meta_on_flush)
|
||||||
release_type := tl.co.getReleaseTypeOnVoluntaryWriteback() //TODO downgrades etc
|
release_type := tl.co.getReleaseTypeOnVoluntaryWriteback() //TODO downgrades etc
|
||||||
req := io.req_bits
|
req := io.req_bits
|
||||||
|
|
||||||
when (io.req_bits.tag_match) {
|
when (io.req_bits.tag_match) {
|
||||||
when (tl.co.isHit(req_cmd, io.req_bits.old_meta.state)) { // set dirty bit
|
when (tl.co.isHit(req_cmd, io.req_bits.old_meta.coh)) { // set dirty bit
|
||||||
state := s_meta_write_req
|
state := s_meta_write_req
|
||||||
line_state := tl.co.newStateOnHit(req_cmd, io.req_bits.old_meta.state)
|
line_state := meta_on_hit
|
||||||
}.otherwise { // upgrade permissions
|
}.otherwise { // upgrade permissions
|
||||||
state := s_refill_req
|
state := s_refill_req
|
||||||
}
|
}
|
||||||
}.otherwise { // writback if necessary and refill
|
}.otherwise { // writback if necessary and refill
|
||||||
state := Mux(tl.co.needsWriteback(io.req_bits.old_meta.state), s_wb_req, s_meta_clear)
|
state := Mux(tl.co.needsWriteback(io.req_bits.old_meta.coh), s_wb_req, s_meta_clear)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,7 +257,7 @@ class MSHR(id: Int)(implicit conf: DCacheConfig) extends Module {
|
|||||||
|
|
||||||
io.meta_write.valid := state === s_meta_write_req || state === s_meta_clear
|
io.meta_write.valid := state === s_meta_write_req || state === s_meta_clear
|
||||||
io.meta_write.bits.idx := req_idx
|
io.meta_write.bits.idx := req_idx
|
||||||
io.meta_write.bits.data.state := Mux(state === s_meta_clear, tl.co.newStateOnFlush(), line_state)
|
io.meta_write.bits.data.coh := Mux(state === s_meta_clear, meta_on_flush, line_state)
|
||||||
io.meta_write.bits.data.tag := io.tag
|
io.meta_write.bits.data.tag := io.tag
|
||||||
io.meta_write.bits.way_en := req.way_en
|
io.meta_write.bits.way_en := req.way_en
|
||||||
|
|
||||||
@ -292,7 +299,7 @@ class MSHRFile(implicit conf: DCacheConfig) extends Module {
|
|||||||
val mem_req = Decoupled(new Acquire)
|
val mem_req = Decoupled(new Acquire)
|
||||||
val mem_resp = new DataWriteReq().asOutput
|
val mem_resp = new DataWriteReq().asOutput
|
||||||
val meta_read = Decoupled(new L1MetaReadReq)
|
val meta_read = Decoupled(new L1MetaReadReq)
|
||||||
val meta_write = Decoupled(new MetaWriteReq(new L1MetaData))
|
val meta_write = Decoupled(new L1MetaWriteReq)
|
||||||
val replay = Decoupled(new Replay)
|
val replay = Decoupled(new Replay)
|
||||||
val mem_grant = Valid(new LogicalNetworkIO(new Grant)).flip
|
val mem_grant = Valid(new LogicalNetworkIO(new Grant)).flip
|
||||||
val mem_finish = Decoupled(new LogicalNetworkIO(new Finish))
|
val mem_finish = Decoupled(new LogicalNetworkIO(new Finish))
|
||||||
@ -316,7 +323,7 @@ class MSHRFile(implicit conf: DCacheConfig) extends Module {
|
|||||||
val wbTagList = Vec.fill(conf.nmshr){Bits()}
|
val wbTagList = Vec.fill(conf.nmshr){Bits()}
|
||||||
val memRespMux = Vec.fill(conf.nmshr){new DataWriteReq}
|
val memRespMux = Vec.fill(conf.nmshr){new DataWriteReq}
|
||||||
val meta_read_arb = Module(new Arbiter(new L1MetaReadReq, conf.nmshr))
|
val meta_read_arb = Module(new Arbiter(new L1MetaReadReq, conf.nmshr))
|
||||||
val meta_write_arb = Module(new Arbiter(new MetaWriteReq(new L1MetaData), conf.nmshr))
|
val meta_write_arb = Module(new Arbiter(new L1MetaWriteReq, conf.nmshr))
|
||||||
val mem_req_arb = Module(new Arbiter(new Acquire, conf.nmshr))
|
val mem_req_arb = Module(new Arbiter(new Acquire, conf.nmshr))
|
||||||
val mem_finish_arb = Module(new Arbiter(new LogicalNetworkIO(new Finish), conf.nmshr))
|
val mem_finish_arb = Module(new Arbiter(new LogicalNetworkIO(new Finish), conf.nmshr))
|
||||||
val wb_req_arb = Module(new Arbiter(new WritebackReq, conf.nmshr))
|
val wb_req_arb = Module(new Arbiter(new WritebackReq, conf.nmshr))
|
||||||
@ -471,16 +478,16 @@ class ProbeUnit(implicit conf: DCacheConfig) extends Module {
|
|||||||
val req = Decoupled(new InternalProbe).flip
|
val req = Decoupled(new InternalProbe).flip
|
||||||
val rep = Decoupled(new Release)
|
val rep = Decoupled(new Release)
|
||||||
val meta_read = Decoupled(new L1MetaReadReq)
|
val meta_read = Decoupled(new L1MetaReadReq)
|
||||||
val meta_write = Decoupled(new MetaWriteReq(new L1MetaData))
|
val meta_write = Decoupled(new L1MetaWriteReq)
|
||||||
val wb_req = Decoupled(new WritebackReq)
|
val wb_req = Decoupled(new WritebackReq)
|
||||||
val way_en = Bits(INPUT, conf.ways)
|
val way_en = Bits(INPUT, conf.ways)
|
||||||
val mshr_rdy = Bool(INPUT)
|
val mshr_rdy = Bool(INPUT)
|
||||||
val line_state = UInt(INPUT, 2)
|
val line_state = new ClientMetadata()(tl.co).asInput
|
||||||
}
|
}
|
||||||
|
|
||||||
val s_reset :: s_invalid :: s_meta_read :: s_meta_resp :: s_mshr_req :: s_release :: s_writeback_req :: s_writeback_resp :: s_meta_write :: Nil = Enum(UInt(), 9)
|
val s_reset :: s_invalid :: s_meta_read :: s_meta_resp :: s_mshr_req :: s_release :: s_writeback_req :: s_writeback_resp :: s_meta_write :: Nil = Enum(UInt(), 9)
|
||||||
val state = Reg(init=s_invalid)
|
val state = Reg(init=s_invalid)
|
||||||
val line_state = Reg(UInt())
|
val line_state = Reg(tl.co.clientMetadataOnFlush.clone)
|
||||||
val way_en = Reg(Bits())
|
val way_en = Reg(Bits())
|
||||||
val req = Reg(new InternalProbe)
|
val req = Reg(new InternalProbe)
|
||||||
val hit = way_en.orR
|
val hit = way_en.orR
|
||||||
@ -522,7 +529,7 @@ class ProbeUnit(implicit conf: DCacheConfig) extends Module {
|
|||||||
|
|
||||||
io.req.ready := state === s_invalid
|
io.req.ready := state === s_invalid
|
||||||
io.rep.valid := state === s_release && !(hit && tl.co.needsWriteback(line_state))
|
io.rep.valid := state === s_release && !(hit && tl.co.needsWriteback(line_state))
|
||||||
io.rep.bits := Release(tl.co.getReleaseTypeOnProbe(req, Mux(hit, line_state, tl.co.newStateOnFlush)), req.addr, req.client_xact_id, req.master_xact_id)
|
io.rep.bits := Release(tl.co.getReleaseTypeOnProbe(req, Mux(hit, line_state, tl.co.clientMetadataOnFlush)), req.addr, req.client_xact_id, req.master_xact_id)
|
||||||
|
|
||||||
io.meta_read.valid := state === s_meta_read
|
io.meta_read.valid := state === s_meta_read
|
||||||
io.meta_read.bits.idx := req.addr
|
io.meta_read.bits.idx := req.addr
|
||||||
@ -531,14 +538,14 @@ class ProbeUnit(implicit conf: DCacheConfig) extends Module {
|
|||||||
io.meta_write.valid := state === s_meta_write
|
io.meta_write.valid := state === s_meta_write
|
||||||
io.meta_write.bits.way_en := way_en
|
io.meta_write.bits.way_en := way_en
|
||||||
io.meta_write.bits.idx := req.addr
|
io.meta_write.bits.idx := req.addr
|
||||||
io.meta_write.bits.data.state := tl.co.newStateOnProbe(req, line_state)
|
io.meta_write.bits.data.coh := tl.co.clientMetadataOnProbe(req, line_state)
|
||||||
io.meta_write.bits.data.tag := req.addr >> UInt(conf.idxbits)
|
io.meta_write.bits.data.tag := req.addr >> UInt(conf.idxbits)
|
||||||
|
|
||||||
io.wb_req.valid := state === s_writeback_req
|
io.wb_req.valid := state === s_writeback_req
|
||||||
io.wb_req.bits.way_en := way_en
|
io.wb_req.bits.way_en := way_en
|
||||||
io.wb_req.bits.idx := req.addr
|
io.wb_req.bits.idx := req.addr
|
||||||
io.wb_req.bits.tag := req.addr >> UInt(conf.idxbits)
|
io.wb_req.bits.tag := req.addr >> UInt(conf.idxbits)
|
||||||
io.wb_req.bits.r_type := tl.co.getReleaseTypeOnProbe(req, Mux(hit, line_state, tl.co.newStateOnFlush))
|
io.wb_req.bits.r_type := tl.co.getReleaseTypeOnProbe(req, Mux(hit, line_state, tl.co.clientMetadataOnFlush))
|
||||||
io.wb_req.bits.client_xact_id := req.client_xact_id
|
io.wb_req.bits.client_xact_id := req.client_xact_id
|
||||||
io.wb_req.bits.master_xact_id := req.master_xact_id
|
io.wb_req.bits.master_xact_id := req.master_xact_id
|
||||||
}
|
}
|
||||||
@ -766,10 +773,10 @@ class HellaCache(implicit conf: DCacheConfig) extends Module {
|
|||||||
io.cpu.xcpt.pf.st := s1_write && dtlb.io.resp.xcpt_st
|
io.cpu.xcpt.pf.st := s1_write && dtlb.io.resp.xcpt_st
|
||||||
|
|
||||||
// tags
|
// tags
|
||||||
def onReset = L1MetaData(UInt(0), tl.co.newStateOnFlush)
|
def onReset = L1Metadata(UInt(0), ClientMetadata(UInt(0))(tl.co))
|
||||||
val meta = Module(new MetaDataArray(onReset _))
|
val meta = Module(new MetadataArray(onReset _))
|
||||||
val metaReadArb = Module(new Arbiter(new MetaReadReq, 5))
|
val metaReadArb = Module(new Arbiter(new MetaReadReq, 5))
|
||||||
val metaWriteArb = Module(new Arbiter(new MetaWriteReq(new L1MetaData), 2))
|
val metaWriteArb = Module(new Arbiter(new L1MetaWriteReq, 2))
|
||||||
metaReadArb.io.out <> meta.io.read
|
metaReadArb.io.out <> meta.io.read
|
||||||
metaWriteArb.io.out <> meta.io.write
|
metaWriteArb.io.out <> meta.io.write
|
||||||
|
|
||||||
@ -804,13 +811,13 @@ class HellaCache(implicit conf: DCacheConfig) extends Module {
|
|||||||
// tag check and way muxing
|
// tag check and way muxing
|
||||||
def wayMap[T <: Data](f: Int => T) = Vec((0 until conf.ways).map(f))
|
def wayMap[T <: Data](f: Int => T) = Vec((0 until conf.ways).map(f))
|
||||||
val s1_tag_eq_way = wayMap((w: Int) => meta.io.resp(w).tag === (s1_addr >> conf.untagbits)).toBits
|
val s1_tag_eq_way = wayMap((w: Int) => meta.io.resp(w).tag === (s1_addr >> conf.untagbits)).toBits
|
||||||
val s1_tag_match_way = wayMap((w: Int) => s1_tag_eq_way(w) && tl.co.isValid(meta.io.resp(w).state)).toBits
|
val s1_tag_match_way = wayMap((w: Int) => s1_tag_eq_way(w) && tl.co.isValid(meta.io.resp(w).coh)).toBits
|
||||||
s1_clk_en := metaReadArb.io.out.valid //TODO: should be metaReadArb.io.out.fire(), but triggers Verilog backend bug
|
s1_clk_en := metaReadArb.io.out.valid //TODO: should be metaReadArb.io.out.fire(), but triggers Verilog backend bug
|
||||||
val s1_writeback = s1_clk_en && !s1_valid && !s1_replay
|
val s1_writeback = s1_clk_en && !s1_valid && !s1_replay
|
||||||
val s2_tag_match_way = RegEnable(s1_tag_match_way, s1_clk_en)
|
val s2_tag_match_way = RegEnable(s1_tag_match_way, s1_clk_en)
|
||||||
val s2_tag_match = s2_tag_match_way.orR
|
val s2_tag_match = s2_tag_match_way.orR
|
||||||
val s2_hit_state = Mux1H(s2_tag_match_way, wayMap((w: Int) => RegEnable(meta.io.resp(w).state, s1_clk_en)))
|
val s2_hit_state = Mux1H(s2_tag_match_way, wayMap((w: Int) => RegEnable(meta.io.resp(w).coh, s1_clk_en)))
|
||||||
val s2_hit = s2_tag_match && tl.co.isHit(s2_req.cmd, s2_hit_state) && s2_hit_state === tl.co.newStateOnHit(s2_req.cmd, s2_hit_state)
|
val s2_hit = s2_tag_match && tl.co.isHit(s2_req.cmd, s2_hit_state) && s2_hit_state === tl.co.clientMetadataOnHit(s2_req.cmd, s2_hit_state)
|
||||||
|
|
||||||
// load-reserved/store-conditional
|
// load-reserved/store-conditional
|
||||||
val lrsc_count = Reg(init=UInt(0))
|
val lrsc_count = Reg(init=UInt(0))
|
||||||
@ -875,7 +882,7 @@ class HellaCache(implicit conf: DCacheConfig) extends Module {
|
|||||||
mshrs.io.req.valid := s2_valid_masked && !s2_hit && (isPrefetch(s2_req.cmd) || isRead(s2_req.cmd) || isWrite(s2_req.cmd))
|
mshrs.io.req.valid := s2_valid_masked && !s2_hit && (isPrefetch(s2_req.cmd) || isRead(s2_req.cmd) || isWrite(s2_req.cmd))
|
||||||
mshrs.io.req.bits := s2_req
|
mshrs.io.req.bits := s2_req
|
||||||
mshrs.io.req.bits.tag_match := s2_tag_match
|
mshrs.io.req.bits.tag_match := s2_tag_match
|
||||||
mshrs.io.req.bits.old_meta := Mux(s2_tag_match, L1MetaData(s2_repl_meta.tag, s2_hit_state), s2_repl_meta)
|
mshrs.io.req.bits.old_meta := Mux(s2_tag_match, L1Metadata(s2_repl_meta.tag, s2_hit_state), s2_repl_meta)
|
||||||
mshrs.io.req.bits.way_en := Mux(s2_tag_match, s2_tag_match_way, s2_replaced_way_en)
|
mshrs.io.req.bits.way_en := Mux(s2_tag_match, s2_tag_match_way, s2_replaced_way_en)
|
||||||
mshrs.io.req.bits.data := s2_req.data
|
mshrs.io.req.bits.data := s2_req.data
|
||||||
when (mshrs.io.req.fire()) { replacer.miss }
|
when (mshrs.io.req.fire()) { replacer.miss }
|
||||||
|
Loading…
Reference in New Issue
Block a user