From 61e3e5b45a29f2c7178ccb5b399bf2d0e024269e Mon Sep 17 00:00:00 2001 From: Howard Mao Date: Thu, 30 Jun 2016 17:55:33 -0700 Subject: [PATCH] more WIP on fixing Bufferless --- uncore/src/main/scala/agents/Broadcast.scala | 2 +- uncore/src/main/scala/agents/Bufferless.scala | 10 +++-- uncore/src/main/scala/agents/Cache.scala | 2 +- uncore/src/main/scala/agents/Trackers.scala | 37 +++++++++++-------- 4 files changed, 31 insertions(+), 20 deletions(-) diff --git a/uncore/src/main/scala/agents/Broadcast.scala b/uncore/src/main/scala/agents/Broadcast.scala index cedda9b9..6c466a92 100644 --- a/uncore/src/main/scala/agents/Broadcast.scala +++ b/uncore/src/main/scala/agents/Broadcast.scala @@ -142,7 +142,7 @@ class BufferedBroadcastAcquireTracker(trackerId: Int)(implicit p: Parameters) can_alloc = Bool(false), next = s_inner_probe) - io.inner.acquire.ready := state === s_idle || iacq_can_merge || iacq_same_xact + io.inner.acquire.ready := state === s_idle || iacq_can_merge || iacq_same_xact // Track which clients yet need to be probed and make Probe message // If a writeback occurs, we can forward its data via the buffer, diff --git a/uncore/src/main/scala/agents/Bufferless.scala b/uncore/src/main/scala/agents/Bufferless.scala index fbece364..eaa5011f 100644 --- a/uncore/src/main/scala/agents/Bufferless.scala +++ b/uncore/src/main/scala/agents/Bufferless.scala @@ -97,9 +97,13 @@ class BufferlessBroadcastAcquireTracker(trackerId: Int)(implicit p: Parameters) can_alloc = Bool(false), next = s_inner_probe) - val iacq_could_accept = state === s_outer_acquire || iacq_can_merge || iacq_same_xact - io.inner.acquire.ready := iacq_could_accept && - (!io.iacq().hasData() || io.outer.acquire.fire()) + // We are never going to merge anything in the bufferless hub + // Therefore, we only need to concern ourselves with the allocated + // transaction and (in case of PutBlock) subsequent tail beats + val iacq_can_forward = iacq_same_xact && !vol_ognt_counter.pending + io.inner.acquire.ready := Mux(io.iacq().hasData(), + state === s_outer_acquire && iacq_can_forward, + state === s_idle && io.alloc.iacq.should) // Track which clients yet need to be probed and make Probe message innerProbe( diff --git a/uncore/src/main/scala/agents/Cache.scala b/uncore/src/main/scala/agents/Cache.scala index b88ece50..889045cd 100644 --- a/uncore/src/main/scala/agents/Cache.scala +++ b/uncore/src/main/scala/agents/Cache.scala @@ -850,7 +850,7 @@ class CacheAcquireTracker(trackerId: Int)(implicit p: Parameters) can_alloc = Bool(true), next = s_meta_read) - io.inner.acquire.ready := state === s_idle || iacq_can_merge || iacq_same_xact + io.inner.acquire.ready := state === s_idle || iacq_can_merge || iacq_same_xact // Begin a transaction by getting the current block metadata // Defined here because of Chisel default wire demands, used in s_meta_resp diff --git a/uncore/src/main/scala/agents/Trackers.scala b/uncore/src/main/scala/agents/Trackers.scala index add92bba..0efeac2a 100644 --- a/uncore/src/main/scala/agents/Trackers.scala +++ b/uncore/src/main/scala/agents/Trackers.scala @@ -407,12 +407,10 @@ trait AcceptsInnerAcquires extends HasAcquireMetadataBuffer val pending_put_data = Reg(init=Bits(0, width = innerDataBeats)) val pending_ignt_data = Reg(init=Bits(0, width = innerDataBeats)) - def iacq_same_xact: Bool = { + def iacq_same_xact: Bool = (xact_iacq.client_xact_id === io.iacq().client_xact_id) && - xact_iacq.hasMultibeatData() && - pending_ignt && - pending_put_data(io.iacq().addr_beat) - } + (xact_iacq.client_id === io.iacq().client_id) && + pending_ignt def iacq_can_merge: Bool def iacq_is_allocating: Bool = state === s_idle && io.alloc.iacq.should && io.inner.acquire.valid def iacq_is_merging: Bool = (iacq_can_merge || iacq_same_xact) && io.inner.acquire.valid @@ -420,7 +418,9 @@ trait AcceptsInnerAcquires extends HasAcquireMetadataBuffer def innerAcquire(can_alloc: Bool, next: UInt) { // Enqueue some metadata information that we'll use to make coherence updates with later - ignt_q.io.enq.valid := iacq_is_allocating || (iacq_is_merging && io.iacq().first()) + ignt_q.io.enq.valid := iacq_is_allocating || + (!iacq_same_xact && pending_ignt && + io.inner.acquire.fire() && io.iacq().first()) ignt_q.io.enq.bits := io.iacq() // Use the outputs of the queue to make further messages @@ -496,10 +496,12 @@ trait AcceptsInnerAcquires extends HasAcquireMetadataBuffer io.inner.grant.bits := ignt_from_iacq io.inner.grant.bits.addr_beat := ignt_data_idx // override based on outgoing counter when (state === s_busy && pending_ignt) { - io.inner.grant.valid := !external_pending && Mux(buffering, + io.inner.grant.valid := !external_pending && Mux(io.ignt().hasData(), - pending_ignt_data(ignt_data_idx), iacq_finished), - io.outer.grant.valid) + Mux(buffering, + pending_ignt_data(ignt_data_idx), + io.outer.grant.valid), + iacq_finished) } } @@ -536,12 +538,17 @@ trait EmitsOuterAcquires extends AcceptsInnerAcquires { beat = xact_addr_beat, trackDown = (g: Grant) => !g.isVoluntary()) - io.outer.acquire.valid := state === s_outer_acquire && - !block_outer_acquire && - (xact_allocate || - Mux(buffering, - !pending_put_data(ognt_counter.up.idx), - io.inner.acquire.valid)) + io.outer.acquire.valid := + state === s_outer_acquire && !block_outer_acquire && + (xact_allocate || + Mux(buffering, + !pending_put_data(ognt_counter.up.idx), + // If not buffering, we should only send an outer acquire if + // the ignt_q is not empty (pending_ignt) and the enqueued + // transaction does not have data or we are receiving the + // inner acquire and it is the same transaction as the one enqueued. + pending_ignt && (!xact_iacq.hasData() || + (io.inner.acquire.valid && iacq_same_xact)))) io.outer.acquire.bits := Mux(caching,