multibeat TL; passes all tests
This commit is contained in:
parent
b7b2923bff
commit
72ea24283b
@ -12,6 +12,7 @@ case object ECCCode extends Field[Option[Code]]
|
|||||||
abstract trait L1CacheParameters extends CacheParameters with CoreParameters {
|
abstract trait L1CacheParameters extends CacheParameters with CoreParameters {
|
||||||
val co = params(TLCoherence)
|
val co = params(TLCoherence)
|
||||||
val code = params(ECCCode).getOrElse(new IdentityCode)
|
val code = params(ECCCode).getOrElse(new IdentityCode)
|
||||||
|
val outerDataBeats = params(TLDataBeats)
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract trait FrontendParameters extends L1CacheParameters
|
abstract trait FrontendParameters extends L1CacheParameters
|
||||||
@ -173,22 +174,13 @@ class ICache extends FrontendModule
|
|||||||
val s2_miss = s2_valid && !s2_any_tag_hit
|
val s2_miss = s2_valid && !s2_any_tag_hit
|
||||||
rdy := state === s_ready && !s2_miss
|
rdy := state === s_ready && !s2_miss
|
||||||
|
|
||||||
var refill_cnt = UInt(0)
|
val ser = Module(new FlowThroughSerializer(io.mem.grant.bits, refillCyclesPerBeat, (g: Grant) => co.messageUpdatesDataArray(g)))
|
||||||
var refill_done = state === s_refill
|
|
||||||
var refill_valid = io.mem.grant.valid
|
|
||||||
var refill_bits = io.mem.grant.bits
|
|
||||||
def doRefill(g: Grant): Bool = Bool(true)
|
|
||||||
if(refillCycles > 1) {
|
|
||||||
val ser = Module(new FlowThroughSerializer(io.mem.grant.bits, refillCycles, doRefill))
|
|
||||||
ser.io.in <> io.mem.grant
|
ser.io.in <> io.mem.grant
|
||||||
refill_cnt = ser.io.cnt
|
val (refill_cnt, refill_wrap) = Counter(ser.io.out.fire(), refillCycles) //TODO Zero width wire
|
||||||
refill_done = ser.io.done
|
val refill_done = state === s_refill && refill_wrap
|
||||||
refill_valid = ser.io.out.valid
|
val refill_valid = ser.io.out.valid
|
||||||
refill_bits = ser.io.out.bits
|
val refill_bits = ser.io.out.bits
|
||||||
ser.io.out.ready := Bool(true)
|
ser.io.out.ready := Bool(true)
|
||||||
} else {
|
|
||||||
io.mem.grant.ready := Bool(true)
|
|
||||||
}
|
|
||||||
//assert(!c.tlco.isVoluntary(refill_bits.payload) || !refill_valid, "UncachedRequestors shouldn't get voluntary grants.")
|
//assert(!c.tlco.isVoluntary(refill_bits.payload) || !refill_valid, "UncachedRequestors shouldn't get voluntary grants.")
|
||||||
|
|
||||||
val repl_way = if (isDM) UInt(0) else LFSR16(s2_miss)(log2Up(nWays)-1,0)
|
val repl_way = if (isDM) UInt(0) else LFSR16(s2_miss)(log2Up(nWays)-1,0)
|
||||||
|
@ -191,7 +191,6 @@ class MSHR(id: Int) extends L1HellaCacheModule {
|
|||||||
val acquire_type = Reg(UInt())
|
val acquire_type = Reg(UInt())
|
||||||
val release_type = Reg(UInt())
|
val release_type = Reg(UInt())
|
||||||
val line_state = Reg(new ClientMetadata()(co))
|
val line_state = Reg(new ClientMetadata()(co))
|
||||||
val refill_count = Reg(UInt(width = log2Up(refillCycles))) // TODO: zero-width wire
|
|
||||||
val req = Reg(new MSHRReqInternal())
|
val req = Reg(new MSHRReqInternal())
|
||||||
|
|
||||||
val req_cmd = io.req_bits.cmd
|
val req_cmd = io.req_bits.cmd
|
||||||
@ -199,9 +198,8 @@ class MSHR(id: Int) extends L1HellaCacheModule {
|
|||||||
val idx_match = req_idx === io.req_bits.addr(untagBits-1,blockOffBits)
|
val idx_match = req_idx === io.req_bits.addr(untagBits-1,blockOffBits)
|
||||||
val sec_rdy = idx_match && (state === s_wb_req || state === s_wb_resp || state === s_meta_clear || (state === s_refill_req || state === s_refill_resp) && !co.needsTransactionOnSecondaryMiss(req_cmd, io.mem_req.bits))
|
val sec_rdy = idx_match && (state === s_wb_req || state === s_wb_resp || state === s_meta_clear || (state === s_refill_req || state === s_refill_resp) && !co.needsTransactionOnSecondaryMiss(req_cmd, io.mem_req.bits))
|
||||||
|
|
||||||
require(isPow2(refillCycles))
|
|
||||||
val reply = io.mem_grant.valid && io.mem_grant.bits.payload.client_xact_id === UInt(id)
|
val reply = io.mem_grant.valid && io.mem_grant.bits.payload.client_xact_id === UInt(id)
|
||||||
val refill_done = reply && (if(refillCycles > 1) refill_count.andR else Bool(true))
|
val (refill_cnt, refill_done) = Counter(reply && co.messageUpdatesDataArray(io.mem_grant.bits.payload), refillCycles) // TODO: Zero width?
|
||||||
val wb_done = reply && (state === s_wb_resp)
|
val wb_done = reply && (state === s_wb_resp)
|
||||||
|
|
||||||
val meta_on_flush = co.clientMetadataOnFlush
|
val meta_on_flush = co.clientMetadataOnFlush
|
||||||
@ -226,7 +224,7 @@ class MSHR(id: Int) extends L1HellaCacheModule {
|
|||||||
when (state === s_refill_resp) {
|
when (state === s_refill_resp) {
|
||||||
when (refill_done) { state := s_meta_write_req }
|
when (refill_done) { state := s_meta_write_req }
|
||||||
when (reply) {
|
when (reply) {
|
||||||
if(refillCycles > 1) refill_count := refill_count + UInt(1)
|
if(refillCycles > 1) refill_cnt := refill_cnt + UInt(1)
|
||||||
line_state := meta_on_grant
|
line_state := meta_on_grant
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -242,13 +240,12 @@ class MSHR(id: Int) extends L1HellaCacheModule {
|
|||||||
when (io.wb_req.fire()) { // s_wb_req
|
when (io.wb_req.fire()) { // s_wb_req
|
||||||
state := s_wb_resp
|
state := s_wb_resp
|
||||||
}
|
}
|
||||||
|
|
||||||
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 := co.getAcquireTypeOnSecondaryMiss(req_cmd, meta_on_flush, io.mem_req.bits)
|
acquire_type := 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 := meta_on_flush
|
line_state := meta_on_flush
|
||||||
refill_count := UInt(0)
|
refill_cnt := UInt(0)
|
||||||
acquire_type := co.getAcquireTypeOnPrimaryMiss(req_cmd, meta_on_flush)
|
acquire_type := co.getAcquireTypeOnPrimaryMiss(req_cmd, meta_on_flush)
|
||||||
release_type := co.getReleaseTypeOnVoluntaryWriteback() //TODO downgrades etc
|
release_type := co.getReleaseTypeOnVoluntaryWriteback() //TODO downgrades etc
|
||||||
req := io.req_bits
|
req := io.req_bits
|
||||||
@ -276,7 +273,7 @@ class MSHR(id: Int) extends L1HellaCacheModule {
|
|||||||
|
|
||||||
io.idx_match := (state != s_invalid) && idx_match
|
io.idx_match := (state != s_invalid) && idx_match
|
||||||
io.mem_resp := req
|
io.mem_resp := req
|
||||||
io.mem_resp.addr := (if(refillCycles > 1) Cat(req_idx, refill_count) else req_idx) << rowOffBits
|
io.mem_resp.addr := (if(refillCycles > 1) Cat(req_idx, refill_cnt) else req_idx) << rowOffBits
|
||||||
io.tag := req.addr >> untagBits
|
io.tag := req.addr >> untagBits
|
||||||
io.req_pri_rdy := state === s_invalid
|
io.req_pri_rdy := state === s_invalid
|
||||||
io.req_sec_rdy := sec_rdy && rpq.io.enq.ready
|
io.req_sec_rdy := sec_rdy && rpq.io.enq.ready
|
||||||
@ -351,7 +348,7 @@ class MSHRFile extends L1HellaCacheModule {
|
|||||||
val memRespMux = Vec.fill(params(NMSHRs)){new DataWriteReq}
|
val memRespMux = Vec.fill(params(NMSHRs)){new DataWriteReq}
|
||||||
val meta_read_arb = Module(new Arbiter(new L1MetaReadReq, params(NMSHRs)))
|
val meta_read_arb = Module(new Arbiter(new L1MetaReadReq, params(NMSHRs)))
|
||||||
val meta_write_arb = Module(new Arbiter(new L1MetaWriteReq, params(NMSHRs)))
|
val meta_write_arb = Module(new Arbiter(new L1MetaWriteReq, params(NMSHRs)))
|
||||||
val mem_req_arb = Module(new Arbiter(new Acquire, params(NMSHRs)))
|
val mem_req_arb = Module(new LockingArbiter(new Acquire, params(NMSHRs), outerDataBeats, co.messageHasData _))
|
||||||
val mem_finish_arb = Module(new Arbiter(new LogicalNetworkIO(new Finish), params(NMSHRs)))
|
val mem_finish_arb = Module(new Arbiter(new LogicalNetworkIO(new Finish), params(NMSHRs)))
|
||||||
val wb_req_arb = Module(new Arbiter(new WritebackReq, params(NMSHRs)))
|
val wb_req_arb = Module(new Arbiter(new WritebackReq, params(NMSHRs)))
|
||||||
val replay_arb = Module(new Arbiter(new ReplayInternal, params(NMSHRs)))
|
val replay_arb = Module(new Arbiter(new ReplayInternal, params(NMSHRs)))
|
||||||
@ -430,7 +427,9 @@ class WritebackUnit extends L1HellaCacheModule {
|
|||||||
val active = Reg(init=Bool(false))
|
val active = Reg(init=Bool(false))
|
||||||
val r1_data_req_fired = Reg(init=Bool(false))
|
val r1_data_req_fired = Reg(init=Bool(false))
|
||||||
val r2_data_req_fired = Reg(init=Bool(false))
|
val r2_data_req_fired = Reg(init=Bool(false))
|
||||||
val cnt = Reg(init = UInt(0, width = log2Up(refillCycles+1)))
|
val cnt = Reg(init = UInt(0, width = log2Up(refillCycles+1))) //TODO Zero width
|
||||||
|
val buf_v = (if(refillCyclesPerBeat > 1) Reg(init=Bits(0, width = refillCyclesPerBeat-1)) else Bits(1))
|
||||||
|
val beat_done = buf_v.andR
|
||||||
val req = Reg(new WritebackReq)
|
val req = Reg(new WritebackReq)
|
||||||
|
|
||||||
io.release.valid := false
|
io.release.valid := false
|
||||||
@ -441,27 +440,22 @@ class WritebackUnit extends L1HellaCacheModule {
|
|||||||
r1_data_req_fired := true
|
r1_data_req_fired := true
|
||||||
cnt := cnt + 1
|
cnt := cnt + 1
|
||||||
}
|
}
|
||||||
if(refillCycles > 1) { // Coalescing buffer inserted
|
|
||||||
when (!r1_data_req_fired && !r2_data_req_fired && cnt === refillCycles) {
|
|
||||||
io.release.valid := true
|
|
||||||
active := !io.release.ready
|
|
||||||
}
|
|
||||||
} else { // No buffer, data released a cycle earlier
|
|
||||||
when (r2_data_req_fired) {
|
when (r2_data_req_fired) {
|
||||||
io.release.valid := true
|
io.release.valid := beat_done
|
||||||
when(!io.release.ready) {
|
when(!io.release.ready) {
|
||||||
r1_data_req_fired := false
|
r1_data_req_fired := false
|
||||||
r2_data_req_fired := false
|
r2_data_req_fired := false
|
||||||
cnt := UInt(0)
|
cnt := cnt - Mux[UInt](Bool(refillCycles > 1) && r1_data_req_fired, 2, 1)
|
||||||
} .otherwise {
|
} .elsewhen(beat_done) { if(refillCyclesPerBeat > 1) buf_v := 0 }
|
||||||
active := false
|
when(!r1_data_req_fired) {
|
||||||
}
|
active := cnt < UInt(refillCycles)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
when (io.req.fire()) {
|
when (io.req.fire()) {
|
||||||
active := true
|
active := true
|
||||||
cnt := 0
|
cnt := 0
|
||||||
|
if(refillCyclesPerBeat > 1) buf_v := 0
|
||||||
req := io.req.bits
|
req := io.req.bits
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -475,25 +469,23 @@ class WritebackUnit extends L1HellaCacheModule {
|
|||||||
|
|
||||||
io.data_req.valid := fire
|
io.data_req.valid := fire
|
||||||
io.data_req.bits.way_en := req.way_en
|
io.data_req.bits.way_en := req.way_en
|
||||||
if(refillCycles > 1) {
|
io.data_req.bits.addr := (if(refillCycles > 1) Cat(req.idx, cnt(log2Up(refillCycles)-1,0))
|
||||||
io.data_req.bits.addr := Cat(req.idx, cnt(log2Up(refillCycles)-1,0)) << rowOffBits
|
else req.idx) << rowOffBits
|
||||||
} else {
|
|
||||||
io.data_req.bits.addr := req.idx << rowOffBits
|
|
||||||
}
|
|
||||||
|
|
||||||
io.release.bits.r_type := req.r_type
|
io.release.bits.r_type := req.r_type
|
||||||
io.release.bits.addr := Cat(req.tag, req.idx).toUInt
|
io.release.bits.addr := Cat(req.tag, req.idx).toUInt
|
||||||
io.release.bits.client_xact_id := req.client_xact_id
|
io.release.bits.client_xact_id := req.client_xact_id
|
||||||
if(refillCycles > 1) {
|
io.release.bits.data :=
|
||||||
|
(if(refillCyclesPerBeat > 1) {
|
||||||
val data_buf = Reg(Bits())
|
val data_buf = Reg(Bits())
|
||||||
when(active && r2_data_req_fired) {
|
when(active && r2_data_req_fired && !beat_done) {
|
||||||
data_buf := Cat(io.data_resp, data_buf(refillCycles*encRowBits-1, encRowBits))
|
data_buf := Cat(io.data_resp, data_buf((refillCyclesPerBeat-1)*encRowBits-1, encRowBits))
|
||||||
|
buf_v := (if(refillCyclesPerBeat > 2)
|
||||||
|
Cat(UInt(1), buf_v(refillCyclesPerBeat-2,1))
|
||||||
|
else UInt(1))
|
||||||
}
|
}
|
||||||
io.release.bits.data := data_buf
|
Cat(io.data_resp, data_buf)
|
||||||
} else {
|
} else { io.data_resp })
|
||||||
io.release.bits.data := io.data_resp
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ProbeUnit extends L1HellaCacheModule {
|
class ProbeUnit extends L1HellaCacheModule {
|
||||||
@ -551,8 +543,12 @@ class ProbeUnit extends L1HellaCacheModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
io.req.ready := state === s_invalid
|
io.req.ready := state === s_invalid
|
||||||
io.rep.valid := state === s_release && !(hit && co.needsWriteback(line_state))
|
io.rep.valid := state === s_release &&
|
||||||
io.rep.bits := Release(co.getReleaseTypeOnProbe(req, Mux(hit, line_state, co.clientMetadataOnFlush)), req.addr, req.client_xact_id)
|
!(hit && co.needsWriteback(line_state)) // Otherwise WBU will issue release
|
||||||
|
io.rep.bits := Release(co.getReleaseTypeOnProbe(req,
|
||||||
|
Mux(hit, line_state, co.clientMetadataOnFlush)),
|
||||||
|
req.addr,
|
||||||
|
req.client_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
|
||||||
@ -878,8 +874,8 @@ class HellaCache extends L1HellaCacheModule {
|
|||||||
metaReadArb.io.in(1) <> mshrs.io.meta_read
|
metaReadArb.io.in(1) <> mshrs.io.meta_read
|
||||||
metaWriteArb.io.in(0) <> mshrs.io.meta_write
|
metaWriteArb.io.in(0) <> mshrs.io.meta_write
|
||||||
|
|
||||||
// probes
|
// probes and releases
|
||||||
val releaseArb = Module(new Arbiter(new Release, 2))
|
val releaseArb = Module(new LockingArbiter(new Release, 2, outerDataBeats, co.messageHasData _))
|
||||||
DecoupledLogicalNetworkIOWrapper(releaseArb.io.out) <> io.mem.release
|
DecoupledLogicalNetworkIOWrapper(releaseArb.io.out) <> io.mem.release
|
||||||
|
|
||||||
val probe = DecoupledLogicalNetworkIOUnwrapper(io.mem.probe)
|
val probe = DecoupledLogicalNetworkIOUnwrapper(io.mem.probe)
|
||||||
@ -895,11 +891,9 @@ class HellaCache extends L1HellaCacheModule {
|
|||||||
|
|
||||||
// refills
|
// refills
|
||||||
def doRefill(g: Grant): Bool = co.messageUpdatesDataArray(g)
|
def doRefill(g: Grant): Bool = co.messageUpdatesDataArray(g)
|
||||||
val refill = if(refillCycles > 1) {
|
val ser = Module(new FlowThroughSerializer(io.mem.grant.bits, refillCyclesPerBeat, doRefill))
|
||||||
val ser = Module(new FlowThroughSerializer(io.mem.grant.bits, refillCycles, doRefill))
|
|
||||||
ser.io.in <> io.mem.grant
|
ser.io.in <> io.mem.grant
|
||||||
ser.io.out
|
val refill = ser.io.out
|
||||||
} else io.mem.grant
|
|
||||||
mshrs.io.mem_grant.valid := refill.fire()
|
mshrs.io.mem_grant.valid := refill.fire()
|
||||||
mshrs.io.mem_grant.bits := refill.bits
|
mshrs.io.mem_grant.bits := refill.bits
|
||||||
refill.ready := writeArb.io.in(1).ready || !doRefill(refill.bits.payload)
|
refill.ready := writeArb.io.in(1).ready || !doRefill(refill.bits.payload)
|
||||||
|
@ -158,50 +158,3 @@ object Random
|
|||||||
private def partition(value: UInt, slices: Int) =
|
private def partition(value: UInt, slices: Int) =
|
||||||
Vec.tabulate(slices)(i => value < round((i << value.getWidth).toDouble / slices))
|
Vec.tabulate(slices)(i => value < round((i << value.getWidth).toDouble / slices))
|
||||||
}
|
}
|
||||||
|
|
||||||
class FlowThroughSerializer[T <: HasTileLinkData](gen: LogicalNetworkIO[T], n: Int, doSer: T => Bool) extends Module {
|
|
||||||
val io = new Bundle {
|
|
||||||
val in = Decoupled(gen.clone).flip
|
|
||||||
val out = Decoupled(gen.clone)
|
|
||||||
val cnt = UInt(OUTPUT, log2Up(n))
|
|
||||||
val done = Bool(OUTPUT)
|
|
||||||
}
|
|
||||||
require(io.in.bits.payload.data.getWidth % n == 0)
|
|
||||||
val narrowWidth = io.in.bits.payload.data.getWidth / n
|
|
||||||
val cnt = Reg(init=UInt(0, width = log2Up(n)))
|
|
||||||
val wrap = cnt === UInt(n-1)
|
|
||||||
val rbits = Reg(init=io.in.bits)
|
|
||||||
val active = Reg(init=Bool(false))
|
|
||||||
|
|
||||||
val shifter = Vec.fill(n){Bits(width = narrowWidth)}
|
|
||||||
(0 until n).foreach {
|
|
||||||
i => shifter(i) := rbits.payload.data((i+1)*narrowWidth-1,i*narrowWidth)
|
|
||||||
}
|
|
||||||
|
|
||||||
io.done := Bool(false)
|
|
||||||
io.cnt := cnt
|
|
||||||
io.in.ready := !active
|
|
||||||
io.out.valid := active || io.in.valid
|
|
||||||
io.out.bits := io.in.bits
|
|
||||||
when(!active && io.in.valid) {
|
|
||||||
when(doSer(io.in.bits.payload)) {
|
|
||||||
cnt := Mux(io.out.ready, UInt(1), UInt(0))
|
|
||||||
rbits := io.in.bits
|
|
||||||
active := Bool(true)
|
|
||||||
}
|
|
||||||
io.done := !doSer(io.in.bits.payload)
|
|
||||||
}
|
|
||||||
when(active) {
|
|
||||||
io.out.bits := rbits
|
|
||||||
io.out.bits.payload.data := shifter(cnt)
|
|
||||||
when(io.out.ready) {
|
|
||||||
cnt := cnt + UInt(1)
|
|
||||||
when(wrap) {
|
|
||||||
cnt := UInt(0)
|
|
||||||
io.done := Bool(true)
|
|
||||||
active := Bool(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user