From 86bdbd65358e253f7742927f74da69c7e9af494e Mon Sep 17 00:00:00 2001 From: Henry Cook Date: Tue, 7 Oct 2014 22:33:10 -0700 Subject: [PATCH] new tshrs, compiles but does not elaborate --- uncore/src/main/scala/cache.scala | 275 +++++++++++++++++--------- uncore/src/main/scala/coherence.scala | 204 ++++++++++--------- uncore/src/main/scala/tilelink.scala | 4 + 3 files changed, 293 insertions(+), 190 deletions(-) diff --git a/uncore/src/main/scala/cache.scala b/uncore/src/main/scala/cache.scala index b4e210b0..9cc99e4e 100644 --- a/uncore/src/main/scala/cache.scala +++ b/uncore/src/main/scala/cache.scala @@ -353,10 +353,14 @@ abstract class L2XactTracker(innerId: String, outerId: String) extends L2HellaCa val c_ack = io.inner.finish.bits val m_gnt = io.outer.grant.bits + def mergeData(acq: Acquire, data: UInt): UInt = { + //TODO wite mask + Mux(co.messageHasData(acq), acq.data, data) + } } class L2VoluntaryReleaseTracker(trackerId: Int, bankId: Int, innerId: String, outerId: String) extends L2XactTracker(innerId, outerId) { - val s_idle :: s_meta_read :: s_meta_resp :: s_meta_write :: s_data_write :: s_ack :: s_busy :: Nil = Enum(UInt(), 6) + val s_idle :: s_meta_read :: s_meta_resp :: s_meta_write :: s_data_write :: s_grant :: s_busy :: Nil = Enum(UInt(), 6) val state = Reg(init=s_idle) val xact = Reg{ new Release } val xact_internal = Reg{ new L2MetaResp } @@ -412,18 +416,26 @@ class L2VoluntaryReleaseTracker(trackerId: Int, bankId: Int, innerId: String, ou } is(s_meta_resp) { when(io.meta_resp.valid) { - xact_internal := io.meta_resp.bits - state := s_meta_write + xact_internal := co.masterMetadataOnRelease(xact, + io.meta_resp.bits.meta.coh, + init_client_id) + state := Mux(io.meta_resp.bits.tag_match, + Mux(co.messageHasData(xact), s_data_write, s_meta_write), + s_grant) } } + is(s_data_write) { + io.data_write.valid := Bool(true) + when(io.data_write.ready) { state := s_meta_write } + } is(s_meta_write) { io.meta_write.valid := Bool(true) - when(io.outer.acquire.ready) { state := s_ack } + when(io.meta_write.ready) { state := s_grant } } - is(s_ack) { + is(s_grant) { io.inner.grant.valid := Bool(true) when(io.inner.grant.ready) { - state := Mux(co.requiresAckForGrant(io.inner.grant.bits.payload.g_type), + state := Mux(co.requiresAckForGrant(c_gnt.payload.g_type), s_busy, s_idle) } } @@ -434,61 +446,71 @@ class L2VoluntaryReleaseTracker(trackerId: Int, bankId: Int, innerId: String, ou } class L2AcquireTracker(trackerId: Int, bankId: Int, innerId: String, outerId: String) extends L2XactTracker(innerId, outerId) { - val s_idle :: s_probe :: s_mem_read :: s_mem_write :: s_make_grant :: s_busy :: Nil = Enum(UInt(), 6) + val s_idle :: s_meta_read :: s_meta_resp :: s_probe :: s_data_read_wb :: s_data_resp_wb :: s_outer_write_wb :: s_outer_read :: s_outer_resp :: s_data_read_hit :: s_data_resp_hit :: s_data_write :: s_outer_write_acq :: s_meta_write :: s_grant :: s_busy :: Nil = Enum(UInt(), 16) val state = Reg(init=s_idle) val xact = Reg{ new Acquire } val xact_internal = Reg{ new L2MetaResp } val init_client_id = Reg(init=UInt(0, width = log2Up(nClients))) //TODO: Will need id reg for merged release xacts - val release_count = if (nClients == 1) UInt(0) else Reg(init=UInt(0, width = log2Up(nClients))) - val probe_flags = Reg(init=Bits(0, width = nClients)) - val curr_p_id = PriorityEncoder(probe_flags) - val pending_outer_write = co.messageHasData(xact) - val pending_outer_read = co.requiresOuterRead(xact.a_type) + val release_count = Reg(init = UInt(0, width = log2Up(nClients))) + val pending_probes = Reg(init = co.dir()) + val curr_p_id = pending_probes.next() + + val is_uncached = co.messageIsUncached(xact) + val tag_match = xact_internal.tag_match + val needs_writeback = co.needsWriteback(xact_internal.meta.coh) + val is_hit = co.isHit(xact, xact_internal.meta.coh) + val needs_probes = co.requiresProbes(xact.a_type, xact_internal.meta.coh) + val c_rel_had_data = Reg{Bool()} + val c_rel_was_voluntary = Reg{Bool()} + val wb_buffer = Reg{xact.data.clone} + + io.has_acquire_conflict := co.isCoherenceConflict(xact.addr, c_acq.payload.addr) && + (state != s_idle) //TODO: Also indexes + io.has_release_conflict := co.isCoherenceConflict(xact.addr, c_rel.payload.addr) && + (state != s_idle) //TODO: Also indexes? + val outer_write_acq = Bundle(Acquire(co.getUncachedWriteAcquireType, - xact.addr, UInt(trackerId), xact.data), - { case TLId => outerId }) - val outer_write_rel = Bundle(Acquire(co.getUncachedWriteAcquireType, - xact.addr, UInt(trackerId), c_rel.payload.data), - { case TLId => outerId }) - val outer_read = Bundle(Acquire(co.getUncachedReadAcquireType, xact.addr, UInt(trackerId)), - { case TLId => outerId }) - - val probe_initial_flags = Bits(width = nClients) - probe_initial_flags := Bits(0) - if (nClients > 1) { - // issue self-probes for uncached read xacts to facilitate I$ coherence - val probe_self = Bool(true) //co.needsSelfProbe(io.inner.acquire.bits.payload) - val myflag = Mux(probe_self, Bits(0), UIntToOH(c_acq.header.src(log2Up(nClients)-1,0))) - probe_initial_flags := ~(io.tile_incoherent | myflag) - } - - io.has_acquire_conflict := co.isCoherenceConflict(xact.addr, c_acq.payload.addr) && (state != s_idle) - io.has_release_conflict := co.isCoherenceConflict(xact.addr, c_rel.payload.addr) && (state != s_idle) - + xact.addr, + UInt(trackerId), + xact.data), { case TLId => outerId }) + val outer_write_wb = Bundle(Acquire(co.getUncachedWriteAcquireType, + Cat(xact_internal.meta.tag, + xact.addr(untagBits-1,blockOffBits)), + UInt(trackerId), + wb_buffer), { case TLId => outerId }) + val outer_read = Bundle(Acquire(co.getUncachedReadAcquireType, + xact.addr, + UInt(trackerId)), { case TLId => outerId }) io.outer.acquire.valid := Bool(false) + io.outer.acquire.bits.payload := outer_read //default io.outer.acquire.bits.header.src := UInt(bankId) - io.outer.acquire.bits.payload := outer_read - io.outer.grant.ready := io.inner.grant.ready + io.outer.grant.ready := Bool(true) //grant.data -> xact.data + val inner_probe_cacq = Probe(co.getProbeType(xact, xact_internal.meta.coh), + xact.addr, + UInt(trackerId)) + val inner_probe_wb = Probe(co.getProbeTypeOnVoluntaryWriteback, + xact.addr, + UInt(trackerId)) + //TODO inner_probe_mprb io.inner.probe.valid := Bool(false) io.inner.probe.bits.header.src := UInt(bankId) io.inner.probe.bits.header.dst := curr_p_id - io.inner.probe.bits.payload := Probe(co.getProbeType(xact, /*xact_internal.meta), TODO*/ - co.masterMetadataOnFlush), - xact.addr, - UInt(trackerId)) + io.inner.probe.bits.payload := Mux(needs_writeback, + inner_probe_wb, + inner_probe_cacq) - val grant_type = co.getGrantType(xact, co.masterMetadataOnFlush)// TODO xact_internal.meta) + val grant_type = co.getGrantType(xact, xact_internal.meta.coh) io.inner.grant.valid := Bool(false) io.inner.grant.bits.header.src := UInt(bankId) io.inner.grant.bits.header.dst := init_client_id io.inner.grant.bits.payload := Grant(grant_type, xact.client_xact_id, UInt(trackerId), - m_gnt.payload.data) + xact.data) io.inner.acquire.ready := Bool(false) io.inner.release.ready := Bool(false) @@ -511,91 +533,154 @@ class L2AcquireTracker(trackerId: Int, bankId: Int, innerId: String, outerId: St io.meta_write.bits.id := UInt(trackerId) io.meta_write.bits.idx := xact.addr(untagBits-1,blockOffBits) io.meta_write.bits.way_en := xact_internal.way_en - io.meta_write.bits.data := xact_internal.meta - - when(io.meta_resp.valid && io.meta_resp.bits.id === UInt(trackerId)) { xact_internal := io.meta_resp.bits } + io.meta_write.bits.data.tag := xact.addr >> UInt(untagBits) + io.meta_write.bits.data.coh := xact_internal.meta.coh switch (state) { is(s_idle) { io.inner.acquire.ready := Bool(true) - val needs_outer_write = co.messageHasData(c_acq.payload) - val needs_outer_read = co.requiresOuterRead(c_acq.payload.a_type) when( io.inner.acquire.valid ) { xact := c_acq.payload init_client_id := c_acq.header.src - probe_flags := probe_initial_flags - if(nClients > 1) { - release_count := PopCount(probe_initial_flags) - state := Mux(probe_initial_flags.orR, s_probe, - Mux(needs_outer_write, s_mem_write, - Mux(needs_outer_read, s_mem_read, s_make_grant))) - } else state := Mux(needs_outer_write, s_mem_write, - Mux(needs_outer_read, s_mem_read, s_make_grant)) + state := s_meta_read } } - // s_read_meta - // xact_internal := resp - is(s_probe) { - // Generate probes - io.inner.probe.valid := probe_flags.orR - when(io.inner.probe.ready) { - probe_flags := probe_flags & ~(UIntToOH(curr_p_id)) + is(s_meta_read) { + io.meta_read.valid := Bool(true) + when(io.meta_read.ready) { state := s_meta_resp } + } + is(s_meta_resp) { + when(io.meta_resp.valid) { + val coh = io.meta_resp.bits.meta.coh + val _tag_match = io.meta_resp.bits.tag_match + val _needs_writeback = co.needsWriteback(coh) + val _is_hit = co.isHit(xact, coh) + val _needs_probes = co.requiresProbes(xact.a_type, coh) + xact_internal := io.meta_resp.bits + when(!_needs_writeback) { + xact_internal.meta.coh := co.masterMetadataOnFlush + } + when(_needs_probes) { + pending_probes := coh.sharers + release_count := coh.sharers.count() + c_rel_had_data := Bool(false) + c_rel_was_voluntary := Bool(false) + } + state := Mux(_tag_match, + Mux(_is_hit, + Mux(_needs_probes, s_probe, s_data_read_hit), + Mux(_needs_probes, s_probe, s_outer_read)), + Mux(_needs_writeback, + Mux(_needs_probes, s_probe, s_data_read_wb), + s_outer_read)) } + } + is(s_probe) { + val skip = io.tile_incoherent(curr_p_id) || + ((curr_p_id === init_client_id) && + !co.requiresSelfProbe(xact.a_type)) + io.inner.probe.valid := !(pending_probes.none() || skip) + when(io.inner.probe.ready || skip) { + pending_probes.pop(curr_p_id) + } + when(skip) { release_count := release_count - UInt(1) } - // Handle releases, which may have data to be written back + // Handle releases, which may have data being written back + io.inner.release.ready := Bool(true) when(io.inner.release.valid) { - //xact_internal.meta.coh := tl.co.masterMetadataOnRelease( - // io.inner.release.bits.payload, - // xact_internal.meta.coh, - // init_client_id) + xact_internal.meta.coh := co.masterMetadataOnRelease( + c_rel.payload, + xact_internal.meta.coh, + c_rel.header.src) when(co.messageHasData(c_rel.payload)) { - io.outer.acquire.valid := Bool(true) - io.outer.acquire.bits.payload := outer_write_rel - when(io.outer.acquire.ready) { - io.inner.release.ready := Bool(true) - if(nClients > 1) release_count := release_count - UInt(1) - when(release_count === UInt(1)) { - state := Mux(pending_outer_write, s_mem_write, - Mux(pending_outer_read, s_mem_read, s_make_grant)) - } + c_rel_had_data := Bool(true) + when(tag_match) { + xact.data := mergeData(xact, io.inner.release.bits.payload.data) + } .otherwise { + wb_buffer := io.inner.release.bits.payload.data } - } .otherwise { - io.inner.release.ready := Bool(true) - if(nClients > 1) release_count := release_count - UInt(1) + } + when(co.isVoluntary(c_rel.payload)) { + c_rel_was_voluntary := Bool(true) + } + when(!co.isVoluntary(c_rel.payload)) { + release_count := release_count - Mux(skip, UInt(2), UInt(1)) when(release_count === UInt(1)) { - state := Mux(pending_outer_write, s_mem_write, - Mux(pending_outer_read, s_mem_read, s_make_grant)) + state := Mux(tag_match, + Mux(is_hit, + Mux(c_rel_had_data, s_meta_write, s_data_read_hit), + s_outer_read), + Mux(c_rel_had_data, s_outer_write_wb, s_data_read_wb)) } } } } - is(s_mem_read) { + is(s_data_read_wb) { + io.data_read.valid := Bool(true) + when(io.data_read.ready) { + state := s_data_resp_wb + } + } + is(s_data_resp_wb) { + when(io.data_resp.valid) { + wb_buffer := io.data_resp.bits + state := s_outer_write_wb + } + } + is(s_outer_write_wb) { + io.outer.acquire.valid := Bool(true) + io.outer.acquire.bits.payload := outer_write_wb + when(io.outer.acquire.ready) { + state := s_outer_read + } + } + is(s_outer_read) { io.outer.acquire.valid := Bool(true) io.outer.acquire.bits.payload := outer_read when(io.outer.acquire.ready) { - state := Mux(co.requiresAckForGrant(grant_type), s_busy, s_idle) + state := s_outer_resp } } - is(s_mem_write) { - io.outer.acquire.valid := Bool(true) - io.outer.acquire.bits.payload := outer_write_acq - when(io.outer.acquire.ready) { - state := Mux(pending_outer_read, s_mem_read, s_make_grant) + is(s_outer_resp) { + io.outer.grant.ready := Bool(true) + when(io.outer.grant.valid) { + xact.data := mergeData(xact, io.outer.grant.bits.payload.data) + //TODO: set pending client state in xact_internal.meta.coh + state := Mux(co.messageHasData(io.outer.grant.bits.payload), + s_data_write, s_data_read_hit) } } - is(s_make_grant) { + is(s_data_read_hit) { + io.data_read.valid := Bool(true) + when(io.data_read.ready) { + state := s_data_resp_hit + } + } + is(s_data_resp_hit) { + when(io.data_resp.valid) { + xact.data := mergeData(xact, io.data_resp.bits.data) + state := s_meta_write + } + } + is(s_data_write) { + io.data_write.valid := Bool(true) + when(io.data_write.ready) { + state := s_meta_write + } + } + is(s_meta_write) { + io.meta_write.valid := Bool(true) + when(io.meta_write.ready) { state := s_grant } + } + is(s_grant) { io.inner.grant.valid := Bool(true) when(io.inner.grant.ready) { - state := Mux(co.requiresAckForGrant(grant_type), s_busy, s_idle) + state := Mux(co.requiresAckForGrant(c_gnt.payload.g_type), + s_busy, s_idle) } } - is(s_busy) { // Nothing left to do but wait for transaction to complete - when(io.outer.grant.valid && m_gnt.payload.client_xact_id === UInt(trackerId)) { - io.inner.grant.valid := Bool(true) - } - when(io.inner.finish.valid && c_ack.payload.master_xact_id === UInt(trackerId)) { - state := s_idle - } + is(s_busy) { + when(io.inner.finish.valid) { state := s_idle } } } } diff --git a/uncore/src/main/scala/coherence.scala b/uncore/src/main/scala/coherence.scala index 778a04f6..5dd87b35 100644 --- a/uncore/src/main/scala/coherence.scala +++ b/uncore/src/main/scala/coherence.scala @@ -51,7 +51,6 @@ class MixedMetadata(inner: CoherencePolicy, outer: CoherencePolicy) extends Cohe */ abstract class DirectoryRepresentation extends Bundle { - val internal: UInt def pop(id: UInt): DirectoryRepresentation def push(id: UInt): DirectoryRepresentation def flush(dummy: Int = 0): DirectoryRepresentation @@ -106,6 +105,7 @@ abstract class CoherencePolicy(val dir: () => DirectoryRepresentation) { def needsTransactionOnSecondaryMiss(cmd: UInt, outstanding: Acquire): Bool def needsTransactionOnCacheControl(cmd: UInt, m: ClientMetadata): Bool def needsWriteback(m: ClientMetadata): Bool + def needsWriteback(m: MasterMetadata): Bool def clientMetadataOnHit(cmd: UInt, m: ClientMetadata): ClientMetadata def clientMetadataOnCacheControl(cmd: UInt): ClientMetadata @@ -114,33 +114,33 @@ abstract class CoherencePolicy(val dir: () => DirectoryRepresentation) { def clientMetadataOnProbe(incoming: Probe, m: ClientMetadata): ClientMetadata def masterMetadataOnFlush: MasterMetadata def masterMetadataOnRelease(incoming: Release, m: MasterMetadata, src: UInt): MasterMetadata + def masterMetadataOnGrant(outgoing: Grant, m: MasterMetadata, dst: UInt): MasterMetadata def getAcquireTypeOnPrimaryMiss(cmd: UInt, m: ClientMetadata): UInt def getAcquireTypeOnSecondaryMiss(cmd: UInt, m: ClientMetadata, outstanding: Acquire): UInt def getProbeType(a: Acquire, m: MasterMetadata): UInt + def getProbeTypeOnVoluntaryWriteback: UInt def getReleaseTypeOnCacheControl(cmd: UInt): UInt def getReleaseTypeOnVoluntaryWriteback(): UInt def getReleaseTypeOnProbe(p: Probe, m: ClientMetadata): UInt def getGrantType(a: Acquire, m: MasterMetadata): UInt def getGrantType(r: Release, m: MasterMetadata): UInt - //def getGrantType(a: Acquire) = getGrantType(a, new NullRepresentation) // TODO - //def getGrantType(r: Release) = getGrantType(r, new NullRepresentation) def messageHasData (rel: SourcedMessage): Bool def messageUpdatesDataArray (reply: Grant): Bool def messageIsUncached(acq: Acquire): Bool - - def isCoherenceConflict(addr1: UInt, addr2: UInt): Bool def isVoluntary(rel: Release): Bool def isVoluntary(gnt: Grant): Bool - def requiresOuterRead(a_type: UInt, m: MasterMetadata): Bool - def requiresOuterWrite(a_type: UInt, m: MasterMetadata): Bool + def requiresOuterRead(a_type: UInt): Bool def requiresOuterWrite(a_type: UInt): Bool def requiresSelfProbe(a_type: UInt): Bool + def requiresProbes(a_type: UInt, m: MasterMetadata): Bool def requiresAckForGrant(g_type: UInt): Bool def requiresAckForRelease(r_type: UInt): Bool def pendingVoluntaryReleaseIsSufficient(r_type: UInt, p_type: UInt): Bool + + def isCoherenceConflict(addr1: UInt, addr2: UInt): Bool } trait UncachedTransactions { @@ -191,6 +191,7 @@ class MICoherence(dir: () => DirectoryRepresentation) extends CoherencePolicyWit def needsWriteback (m: ClientMetadata): Bool = { needsTransactionOnCacheControl(M_INV, m) } + def needsWriteback(m: MasterMetadata) = isValid(m) def clientMetadataOnHit(cmd: UInt, m: ClientMetadata) = m def clientMetadataOnCacheControl(cmd: UInt) = ClientMetadata( @@ -214,16 +215,19 @@ class MICoherence(dir: () => DirectoryRepresentation) extends CoherencePolicyWit probeCopy -> m.state )))(this) def masterMetadataOnFlush = MasterMetadata(masterInvalid)(this) - def masterMetadataOnRelease(incoming: Release, m: MasterMetadata, src: UInt) = { - val popped = m.sharers.pop(src) - val next = MasterMetadata(Mux(popped.none(), masterInvalid, masterValid), popped)(this) - def is(r: UInt) = incoming.r_type === r + def masterMetadataOnRelease(r: Release, m: MasterMetadata, src: UInt) = { + val next = MasterMetadata(masterValid, m.sharers.pop(src))(this) MuxBundle(m, Array( - is(releaseVoluntaryInvalidateData) -> next, - is(releaseInvalidateData) -> next, - is(releaseCopyData) -> m, - is(releaseInvalidateAck) -> next, - is(releaseCopyAck) -> m + r.is(releaseVoluntaryInvalidateData) -> next, + r.is(releaseInvalidateData) -> next, + r.is(releaseInvalidateAck) -> next + )) + } + def masterMetadataOnGrant(g: Grant, m: MasterMetadata, dst: UInt) = { + val cached = MasterMetadata(masterValid, m.sharers.push(dst))(this) + val uncached = MasterMetadata(masterValid, m.sharers)(this) + MuxBundle(uncached, Array( + g.is(grantReadExclusive) -> cached )) } @@ -292,6 +296,7 @@ class MICoherence(dir: () => DirectoryRepresentation) extends CoherencePolicyWit acquireAtomicUncached -> probeInvalidate )) } + def getProbeTypeOnVoluntaryWriteback: UInt = probeInvalidate def requiresOuterRead(a_type: UInt) = { (a_type != acquireWriteUncached) @@ -299,11 +304,10 @@ class MICoherence(dir: () => DirectoryRepresentation) extends CoherencePolicyWit def requiresOuterWrite(a_type: UInt) = { (a_type === acquireWriteUncached) } - def requiresOuterRead(a_type: UInt, m: MasterMetadata) = requiresOuterRead(a_type) - def requiresOuterWrite(a_type: UInt, m: MasterMetadata) = requiresOuterWrite(a_type) def requiresAckForGrant(g_type: UInt) = g_type != grantVoluntaryAck def requiresAckForRelease(r_type: UInt) = Bool(false) - def requiresSelfProbe(a_type: UInt) = Bool(false) + def requiresSelfProbe(a_type: UInt) = a_type === acquireReadUncached + def requiresProbes(a_type: UInt, m: MasterMetadata) = !m.sharers.none() def pendingVoluntaryReleaseIsSufficient(r_type: UInt, p_type: UInt): Bool = (r_type === releaseVoluntaryInvalidateData) } @@ -346,6 +350,7 @@ class MEICoherence(dir: () => DirectoryRepresentation) extends CoherencePolicyWi def needsWriteback (m: ClientMetadata): Bool = { needsTransactionOnCacheControl(M_INV, m) } + def needsWriteback(m: MasterMetadata) = isValid(m) def clientMetadataOnHit(cmd: UInt, m: ClientMetadata) = ClientMetadata(Mux(isWrite(cmd), clientExclusiveDirty, m.state))(this) @@ -374,18 +379,20 @@ class MEICoherence(dir: () => DirectoryRepresentation) extends CoherencePolicyWi probeCopy -> m.state )))(this) def masterMetadataOnFlush = MasterMetadata(masterInvalid)(this) - def masterMetadataOnRelease(incoming: Release, m: MasterMetadata, src: UInt) = { - val popped = m.sharers.pop(src) - val next = MasterMetadata(Mux(popped.none(), masterInvalid, masterValid), popped)(this) - def is(r: UInt) = incoming.r_type === r + def masterMetadataOnRelease(r: Release, m: MasterMetadata, src: UInt) = { + val next = MasterMetadata(masterValid, m.sharers.pop(src))(this) MuxBundle(m, Array( - is(releaseVoluntaryInvalidateData) -> next, - is(releaseInvalidateData) -> next, - is(releaseDowngradeData) -> m, - is(releaseCopyData) -> m, - is(releaseInvalidateAck) -> next, - is(releaseDowngradeAck) -> m, - is(releaseCopyAck) -> m + r.is(releaseVoluntaryInvalidateData) -> next, + r.is(releaseInvalidateData) -> next, + r.is(releaseInvalidateAck) -> next + )) + } + def masterMetadataOnGrant(g: Grant, m: MasterMetadata, dst: UInt) = { + val cached = MasterMetadata(masterValid, m.sharers.push(dst))(this) + val uncached = MasterMetadata(masterValid, m.sharers)(this) + MuxBundle(uncached, Array( + g.is(grantReadExclusive) -> cached, + g.is(grantReadExclusiveAck) -> cached )) } @@ -462,6 +469,7 @@ class MEICoherence(dir: () => DirectoryRepresentation) extends CoherencePolicyWi acquireAtomicUncached -> probeInvalidate )) } + def getProbeTypeOnVoluntaryWriteback: UInt = probeInvalidate def requiresOuterRead(a_type: UInt) = { (a_type != acquireWriteUncached) @@ -469,25 +477,25 @@ class MEICoherence(dir: () => DirectoryRepresentation) extends CoherencePolicyWi def requiresOuterWrite(a_type: UInt) = { (a_type === acquireWriteUncached) } - def requiresOuterRead(a_type: UInt, m: MasterMetadata) = requiresOuterRead(a_type) - def requiresOuterWrite(a_type: UInt, m: MasterMetadata) = requiresOuterWrite(a_type) def requiresAckForGrant(g_type: UInt) = g_type != grantVoluntaryAck def requiresAckForRelease(r_type: UInt) = Bool(false) - def requiresSelfProbe(a_type: UInt) = Bool(false) + def requiresSelfProbe(a_type: UInt) = a_type === acquireReadUncached + def requiresProbes(a_type: UInt, m: MasterMetadata) = !m.sharers.none() def pendingVoluntaryReleaseIsSufficient(r_type: UInt, p_type: UInt): Bool = (r_type === releaseVoluntaryInvalidateData) } class MSICoherence(dir: () => DirectoryRepresentation) extends CoherencePolicyWithUncached(dir) { def nClientStates = 3 - def nMasterStates = 3 + def nMasterStates = 2 def nAcquireTypes = 7 def nProbeTypes = 3 def nReleaseTypes = 7 def nGrantTypes = 9 val clientInvalid :: clientShared :: clientExclusiveDirty :: Nil = Enum(UInt(), nClientStates) - val masterInvalid :: masterShared :: masterExclusive :: Nil = Enum(UInt(), nMasterStates) + //val masterInvalid :: masterShared :: masterExclusive :: Nil = Enum(UInt(), nMasterStates) + val masterInvalid :: masterValid :: Nil = Enum(UInt(), nMasterStates) val acquireReadShared :: acquireReadExclusive :: acquireReadUncached :: acquireWriteUncached :: acquireReadWordUncached :: acquireWriteWordUncached :: acquireAtomicUncached :: Nil = Enum(UInt(), nAcquireTypes) val probeInvalidate :: probeDowngrade :: probeCopy :: Nil = Enum(UInt(), nProbeTypes) @@ -522,6 +530,7 @@ class MSICoherence(dir: () => DirectoryRepresentation) extends CoherencePolicyWi def needsWriteback (m: ClientMetadata): Bool = { needsTransactionOnCacheControl(M_INV, m) } + def needsWriteback(m: MasterMetadata) = isValid(m) def clientMetadataOnHit(cmd: UInt, m: ClientMetadata) = ClientMetadata(Mux(isWrite(cmd), clientExclusiveDirty, m.state))(this) @@ -549,20 +558,21 @@ class MSICoherence(dir: () => DirectoryRepresentation) extends CoherencePolicyWi probeCopy -> m.state )))(this) def masterMetadataOnFlush = MasterMetadata(masterInvalid)(this) - def masterMetadataOnRelease(incoming: Release, m: MasterMetadata, src: UInt) = { - val popped = m.sharers.pop(src) - val next = MasterMetadata( - Mux(popped.none(), masterInvalid, - Mux(popped.one(), masterExclusive, masterShared)), popped)(this) - def is(r: UInt) = incoming.r_type === r + def masterMetadataOnRelease(r: Release, m: MasterMetadata, src: UInt) = { + val next = MasterMetadata(masterValid, m.sharers.pop(src))(this) MuxBundle(m, Array( - is(releaseVoluntaryInvalidateData) -> next, - is(releaseInvalidateData) -> next, - is(releaseDowngradeData) -> m, - is(releaseCopyData) -> m, - is(releaseInvalidateAck) -> next, - is(releaseDowngradeAck) -> m, - is(releaseCopyAck) -> m + r.is(releaseVoluntaryInvalidateData) -> next, + r.is(releaseInvalidateData) -> next, + r.is(releaseInvalidateAck) -> next + )) + } + def masterMetadataOnGrant(g: Grant, m: MasterMetadata, dst: UInt) = { + val cached = MasterMetadata(masterValid, m.sharers.push(dst))(this) + val uncached = MasterMetadata(masterValid, m.sharers)(this) + MuxBundle(uncached, Array( + g.is(grantReadShared) -> cached, + g.is(grantReadExclusive) -> cached, + g.is(grantReadExclusiveAck) -> cached )) } @@ -612,7 +622,7 @@ class MSICoherence(dir: () => DirectoryRepresentation) extends CoherencePolicyWi def getGrantType(a: Acquire, m: MasterMetadata): UInt = { MuxLookup(a.a_type, grantReadUncached, Array( - acquireReadShared -> Mux(m.sharers.count() > UInt(0), grantReadShared, grantReadExclusive), + acquireReadShared -> Mux(!m.sharers.none(), grantReadShared, grantReadExclusive), acquireReadExclusive -> grantReadExclusive, acquireReadUncached -> grantReadUncached, acquireWriteUncached -> grantWriteUncached, @@ -635,6 +645,7 @@ class MSICoherence(dir: () => DirectoryRepresentation) extends CoherencePolicyWi acquireWriteUncached -> probeInvalidate )) } + def getProbeTypeOnVoluntaryWriteback: UInt = probeInvalidate def requiresOuterRead(a_type: UInt) = { (a_type != acquireWriteUncached) @@ -642,25 +653,25 @@ class MSICoherence(dir: () => DirectoryRepresentation) extends CoherencePolicyWi def requiresOuterWrite(a_type: UInt) = { (a_type === acquireWriteUncached) } - def requiresOuterRead(a_type: UInt, m: MasterMetadata) = requiresOuterRead(a_type) - def requiresOuterWrite(a_type: UInt, m: MasterMetadata) = requiresOuterWrite(a_type) def requiresAckForGrant(g_type: UInt) = g_type != grantVoluntaryAck def requiresAckForRelease(r_type: UInt) = Bool(false) - def requiresSelfProbe(a_type: UInt) = Bool(false) + def requiresSelfProbe(a_type: UInt) = a_type === acquireReadUncached + def requiresProbes(a_type: UInt, m: MasterMetadata) = !m.sharers.none() def pendingVoluntaryReleaseIsSufficient(r_type: UInt, p_type: UInt): Bool = (r_type === releaseVoluntaryInvalidateData) } class MESICoherence(dir: () => DirectoryRepresentation) extends CoherencePolicyWithUncached(dir) { def nClientStates = 4 - def nMasterStates = 3 + def nMasterStates = 2 def nAcquireTypes = 7 def nProbeTypes = 3 def nReleaseTypes = 7 def nGrantTypes = 9 val clientInvalid :: clientShared :: clientExclusiveClean :: clientExclusiveDirty :: Nil = Enum(UInt(), nClientStates) - val masterInvalid :: masterShared :: masterExclusive :: Nil = Enum(UInt(), nMasterStates) + //val masterInvalid :: masterShared :: masterExclusive :: Nil = Enum(UInt(), nMasterStates) + val masterInvalid :: masterValid :: Nil = Enum(UInt(), nMasterStates) val acquireReadShared :: acquireReadExclusive :: acquireReadUncached :: acquireWriteUncached :: acquireReadWordUncached :: acquireWriteWordUncached :: acquireAtomicUncached :: Nil = Enum(UInt(), nAcquireTypes) val probeInvalidate :: probeDowngrade :: probeCopy :: Nil = Enum(UInt(), nProbeTypes) @@ -695,6 +706,7 @@ class MESICoherence(dir: () => DirectoryRepresentation) extends CoherencePolicyW def needsWriteback (m: ClientMetadata): Bool = { needsTransactionOnCacheControl(M_INV, m) } + def needsWriteback(m: MasterMetadata) = isValid(m) def clientMetadataOnHit(cmd: UInt, m: ClientMetadata) = ClientMetadata(Mux(isWrite(cmd), clientExclusiveDirty, m.state))(this) @@ -723,20 +735,21 @@ class MESICoherence(dir: () => DirectoryRepresentation) extends CoherencePolicyW probeCopy -> m.state )))(this) def masterMetadataOnFlush = MasterMetadata(masterInvalid)(this) - def masterMetadataOnRelease(incoming: Release, m: MasterMetadata, src: UInt) = { - val popped = m.sharers.pop(src) - val next = MasterMetadata( - Mux(popped.none(), masterInvalid, - Mux(popped.one(), masterExclusive, masterShared)), popped)(this) - def is(r: UInt) = incoming.r_type === r + def masterMetadataOnRelease(r: Release, m: MasterMetadata, src: UInt) = { + val next = MasterMetadata(masterValid, m.sharers.pop(src))(this) MuxBundle(m, Array( - is(releaseVoluntaryInvalidateData) -> next, - is(releaseInvalidateData) -> next, - is(releaseDowngradeData) -> m, - is(releaseCopyData) -> m, - is(releaseInvalidateAck) -> next, - is(releaseDowngradeAck) -> m, - is(releaseCopyAck) -> m + r.is(releaseVoluntaryInvalidateData) -> next, + r.is(releaseInvalidateData) -> next, + r.is(releaseInvalidateAck) -> next + )) + } + def masterMetadataOnGrant(g: Grant, m: MasterMetadata, dst: UInt) = { + val cached = MasterMetadata(masterValid, m.sharers.push(dst))(this) + val uncached = MasterMetadata(masterValid, m.sharers)(this) + MuxBundle(uncached, Array( + g.is(grantReadShared) -> cached, + g.is(grantReadExclusive) -> cached, + g.is(grantReadExclusiveAck) -> cached )) } @@ -786,7 +799,7 @@ class MESICoherence(dir: () => DirectoryRepresentation) extends CoherencePolicyW def getGrantType(a: Acquire, m: MasterMetadata): UInt = { MuxLookup(a.a_type, grantReadUncached, Array( - acquireReadShared -> Mux(m.sharers.count() > UInt(0), grantReadShared, grantReadExclusive), + acquireReadShared -> Mux(!m.sharers.none(), grantReadShared, grantReadExclusive), acquireReadExclusive -> grantReadExclusive, acquireReadUncached -> grantReadUncached, acquireWriteUncached -> grantWriteUncached, @@ -813,6 +826,7 @@ class MESICoherence(dir: () => DirectoryRepresentation) extends CoherencePolicyW acquireAtomicUncached -> probeInvalidate )) } + def getProbeTypeOnVoluntaryWriteback: UInt = probeInvalidate def requiresOuterRead(a_type: UInt) = { (a_type != acquireWriteUncached) @@ -820,26 +834,26 @@ class MESICoherence(dir: () => DirectoryRepresentation) extends CoherencePolicyW def requiresOuterWrite(a_type: UInt) = { (a_type === acquireWriteUncached) } - def requiresOuterRead(a_type: UInt, m: MasterMetadata) = requiresOuterRead(a_type) - def requiresOuterWrite(a_type: UInt, m: MasterMetadata) = requiresOuterWrite(a_type) def requiresAckForGrant(g_type: UInt) = g_type != grantVoluntaryAck def requiresAckForRelease(r_type: UInt) = Bool(false) - def requiresSelfProbe(a_type: UInt) = Bool(false) + def requiresSelfProbe(a_type: UInt) = a_type === acquireReadUncached + def requiresProbes(a_type: UInt, m: MasterMetadata) = !m.sharers.none() def pendingVoluntaryReleaseIsSufficient(r_type: UInt, p_type: UInt): Bool = (r_type === releaseVoluntaryInvalidateData) } class MigratoryCoherence(dir: () => DirectoryRepresentation) extends CoherencePolicyWithUncached(dir) { def nClientStates = 7 - def nMasterStates = 3 + def nMasterStates = 2 def nAcquireTypes = 8 def nProbeTypes = 4 def nReleaseTypes = 11 def nGrantTypes = 9 val clientInvalid :: clientShared :: clientExclusiveClean :: clientExclusiveDirty :: clientSharedByTwo :: clientMigratoryClean :: clientMigratoryDirty :: Nil = Enum(UInt(), nClientStates) - val masterInvalid :: masterShared :: masterExclusive :: Nil = Enum(UInt(), nMasterStates) + //val masterInvalid :: masterShared :: masterExclusive :: Nil = Enum(UInt(), nMasterStates) + val masterInvalid :: masterValid :: Nil = Enum(UInt(), nMasterStates) val acquireReadShared :: acquireReadExclusive :: acquireReadUncached :: acquireWriteUncached :: acquireReadWordUncached :: acquireWriteWordUncached :: acquireAtomicUncached :: acquireInvalidateOthers :: Nil = Enum(UInt(), nAcquireTypes) val probeInvalidate :: probeDowngrade :: probeCopy :: probeInvalidateOthers :: Nil = Enum(UInt(), nProbeTypes) @@ -873,6 +887,7 @@ class MigratoryCoherence(dir: () => DirectoryRepresentation) extends CoherencePo def needsWriteback (m: ClientMetadata): Bool = { needsTransactionOnCacheControl(M_INV, m) } + def needsWriteback(m: MasterMetadata) = isValid(m) def clientMetadataOnHit(cmd: UInt, m: ClientMetadata) = ClientMetadata( Mux(isWrite(cmd), MuxLookup(m.state, clientExclusiveDirty, Array( @@ -914,25 +929,24 @@ class MigratoryCoherence(dir: () => DirectoryRepresentation) extends CoherencePo clientMigratoryDirty -> clientInvalid)) )))(this) def masterMetadataOnFlush = MasterMetadata(masterInvalid)(this) - def masterMetadataOnRelease(incoming: Release, m: MasterMetadata, src: UInt) = { - val popped = m.sharers.pop(src) - val next = MasterMetadata( - Mux(popped.none(), masterInvalid, - Mux(popped.one(), masterExclusive, masterShared)), - popped)(this) - def is(r: UInt) = incoming.r_type === r + def masterMetadataOnRelease(r: Release, m: MasterMetadata, src: UInt) = { + val next = MasterMetadata(masterValid, m.sharers.pop(src))(this) MuxBundle(m, Array( - is(releaseVoluntaryInvalidateData) -> next, - is(releaseInvalidateData) -> next, - is(releaseDowngradeData) -> m, - is(releaseCopyData) -> m, - is(releaseInvalidateAck) -> next, - is(releaseDowngradeAck) -> m, - is(releaseCopyAck) -> m, - is(releaseDowngradeDataMigratory) -> m, - is(releaseDowngradeAckHasCopy) -> m, - is(releaseInvalidateDataMigratory) -> next, - is(releaseInvalidateAckMigratory) -> next + r.is(releaseVoluntaryInvalidateData) -> next, + r.is(releaseInvalidateData) -> next, + r.is(releaseInvalidateAck) -> next, + r.is(releaseInvalidateDataMigratory) -> next, + r.is(releaseInvalidateAckMigratory) -> next + )) + } + def masterMetadataOnGrant(g: Grant, m: MasterMetadata, dst: UInt) = { + val cached = MasterMetadata(masterValid, m.sharers.push(dst))(this) + val uncached = MasterMetadata(masterValid, m.sharers)(this) + MuxBundle(uncached, Array( + g.is(grantReadShared) -> cached, + g.is(grantReadExclusive) -> cached, + g.is(grantReadExclusiveAck) -> cached, + g.is(grantReadMigratory) -> cached )) } @@ -983,7 +997,7 @@ class MigratoryCoherence(dir: () => DirectoryRepresentation) extends CoherencePo def getGrantType(a: Acquire, m: MasterMetadata): UInt = { MuxLookup(a.a_type, grantReadUncached, Array( - acquireReadShared -> Mux(m.sharers.count() > UInt(0), grantReadShared, grantReadExclusive), //TODO: what is count? Depend on release.p_type??? + acquireReadShared -> Mux(!m.sharers.none(), grantReadShared, grantReadExclusive), //TODO: what is count? Depend on release.p_type??? acquireReadExclusive -> grantReadExclusive, acquireReadUncached -> grantReadUncached, acquireWriteUncached -> grantWriteUncached, @@ -1012,6 +1026,7 @@ class MigratoryCoherence(dir: () => DirectoryRepresentation) extends CoherencePo acquireInvalidateOthers -> probeInvalidateOthers )) } + def getProbeTypeOnVoluntaryWriteback: UInt = probeInvalidate def requiresOuterRead(a_type: UInt) = { (a_type != acquireWriteUncached && a_type != acquireInvalidateOthers) @@ -1019,12 +1034,11 @@ class MigratoryCoherence(dir: () => DirectoryRepresentation) extends CoherencePo def requiresOuterWrite(a_type: UInt) = { (a_type === acquireWriteUncached || a_type === acquireWriteWordUncached || a_type === acquireAtomicUncached) } - def requiresOuterRead(a_type: UInt, m: MasterMetadata) = requiresOuterRead(a_type) - def requiresOuterWrite(a_type: UInt, m: MasterMetadata) = requiresOuterWrite(a_type) def requiresAckForGrant(g_type: UInt) = g_type != grantVoluntaryAck def requiresAckForRelease(r_type: UInt) = Bool(false) - def requiresSelfProbe(a_type: UInt) = Bool(false) + def requiresSelfProbe(a_type: UInt) = a_type === acquireReadUncached + def requiresProbes(a_type: UInt, m: MasterMetadata) = !m.sharers.none() def pendingVoluntaryReleaseIsSufficient(r_type: UInt, p_type: UInt): Bool = (r_type === releaseVoluntaryInvalidateData) } diff --git a/uncore/src/main/scala/tilelink.scala b/uncore/src/main/scala/tilelink.scala index 51864fe1..46ae899e 100644 --- a/uncore/src/main/scala/tilelink.scala +++ b/uncore/src/main/scala/tilelink.scala @@ -77,6 +77,7 @@ class Acquire extends ClientSourcedMessage val write_mask = Bits(width = params(TLWriteMaskBits)) val subword_addr = Bits(width = params(TLWordAddrBits)) val atomic_opcode = Bits(width = params(TLAtomicOpBits)) + def is(t: UInt) = a_type === t } object Probe @@ -94,6 +95,7 @@ class Probe extends MasterSourcedMessage with HasPhysicalAddress with HasMasterTransactionId { val p_type = UInt(width = params(TLCoherence).probeTypeWidth) + def is(t: UInt) = p_type === t } object Release @@ -127,6 +129,7 @@ class Release extends ClientSourcedMessage with HasMasterTransactionId with HasTileLinkData { val r_type = UInt(width = params(TLCoherence).releaseTypeWidth) + def is(t: UInt) = r_type === t } object Grant @@ -151,6 +154,7 @@ class Grant extends MasterSourcedMessage with HasClientTransactionId with HasMasterTransactionId { val g_type = UInt(width = params(TLCoherence).grantTypeWidth) + def is(t: UInt) = g_type === t } class Finish extends ClientSourcedMessage with HasMasterTransactionId