From 86e31be8202f636df619630d7d444f03001b8b9b Mon Sep 17 00:00:00 2001 From: Howard Mao Date: Wed, 20 Jul 2016 18:23:27 -0700 Subject: [PATCH] fix lockup from back to back releases with data --- uncore/src/main/scala/agents/Broadcast.scala | 3 ++- uncore/src/main/scala/agents/Bufferless.scala | 4 ++- uncore/src/main/scala/agents/Cache.scala | 3 ++- uncore/src/main/scala/agents/Trackers.scala | 25 ++++++++++++++++--- 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/uncore/src/main/scala/agents/Broadcast.scala b/uncore/src/main/scala/agents/Broadcast.scala index 86e02c5f..119570ce 100644 --- a/uncore/src/main/scala/agents/Broadcast.scala +++ b/uncore/src/main/scala/agents/Broadcast.scala @@ -160,7 +160,8 @@ class BufferedBroadcastAcquireTracker(trackerId: Int)(implicit p: Parameters) !all_pending_done && !io.outer.grant.fire() && !io.inner.grant.fire() && - !vol_ignt_counter.pending + !vol_ignt_counter.pending && + !blockInnerRelease() innerRelease(block_vol_ignt = vol_ognt_counter.pending) diff --git a/uncore/src/main/scala/agents/Bufferless.scala b/uncore/src/main/scala/agents/Bufferless.scala index 7c67edc4..39276c2b 100644 --- a/uncore/src/main/scala/agents/Bufferless.scala +++ b/uncore/src/main/scala/agents/Bufferless.scala @@ -120,6 +120,7 @@ class BufferlessBroadcastAcquireTracker(trackerId: Int)(implicit p: Parameters) def irel_can_merge = io.irel().conflicts(xact_addr_block) && io.irel().isVoluntary() && !vol_ignt_counter.pending && + !(io.irel().hasData() && ognt_counter.pending) && (state =/= s_idle) innerRelease(block_vol_ignt = vol_ognt_counter.pending) @@ -131,7 +132,8 @@ class BufferlessBroadcastAcquireTracker(trackerId: Int)(implicit p: Parameters) // If there was a writeback, forward it outwards outerRelease( coh = outer_coh.onHit(M_XWR), - buffering = Bool(false)) + buffering = Bool(false), + block_orel = !irel_could_accept) // Send outer request for miss outerAcquire( diff --git a/uncore/src/main/scala/agents/Cache.scala b/uncore/src/main/scala/agents/Cache.scala index 171555ff..52bff518 100644 --- a/uncore/src/main/scala/agents/Cache.scala +++ b/uncore/src/main/scala/agents/Cache.scala @@ -1050,7 +1050,8 @@ class L2WritebackUnit(val trackerId: Int)(implicit p: Parameters) extends XactTr io.irel().isVoluntary() && (state =/= s_idle) && !(state === s_busy && all_pending_done) && - !vol_ignt_counter.pending + !vol_ignt_counter.pending && + !blockInnerRelease() io.inner.release.ready := irel_can_merge || irel_same_xact diff --git a/uncore/src/main/scala/agents/Trackers.scala b/uncore/src/main/scala/agents/Trackers.scala index 5b8d3080..d695df8d 100644 --- a/uncore/src/main/scala/agents/Trackers.scala +++ b/uncore/src/main/scala/agents/Trackers.scala @@ -294,13 +294,28 @@ trait EmitsVoluntaryReleases extends HasVoluntaryReleaseMetadataBuffer { val pending_orel_data = Reg(init=Bits(0, width = innerDataBeats)) val vol_ognt_counter = Wire(new TwoWayBeatCounterStatus) val pending_orel = pending_orel_send || pending_orel_data.orR || vol_ognt_counter.pending + val sending_orel = Reg(init = Bool(false)) + + // Block acceptance of inner releases if we have already started sending + // outer releases, but have not yet sent out the beat corresponding to the + // inner release. This function must be included in io.inner.release.ready + // if it is possible to start accepting a new inner release as the previous + // outer release is still being sent. DO NOT include this in the + // io.inner.release.ready if the releases are not buffered + // (i.e. io.inner.release and io.outer.release combinationally linked). + def blockInnerRelease(rel: ReleaseMetadata = io.irel()): Bool = { + val waiting_to_send = sending_orel && pending_orel_data(rel.addr_beat) + val sending_now = io.outer.release.fire() && rel.addr_beat === io.orel().addr_beat + rel.hasData() && (waiting_to_send || sending_now) + } def outerRelease( coh: ClientMetadata, buffering: Bool = Bool(true), data: UInt = io.irel().data, add_pending_data_bits: UInt = UInt(0), - add_pending_send_bit: Bool = Bool(false)) { + add_pending_send_bit: Bool = Bool(false), + block_orel: Bool = Bool(false)) { when (state =/= s_idle || io.alloc.irel.should) { pending_orel_data := (pending_orel_data | @@ -309,7 +324,11 @@ trait EmitsVoluntaryReleases extends HasVoluntaryReleaseMetadataBuffer { dropPendingBitWhenBeatHasData(io.outer.release) } when (add_pending_send_bit) { pending_orel_send := Bool(true) } - when (io.outer.release.fire()) { pending_orel_send := Bool(false) } + when (io.outer.release.fire()) { + when (io.outer.release.bits.first()) { sending_orel := Bool(true) } + when (io.outer.release.bits.last()) { sending_orel := Bool(false) } + pending_orel_send := Bool(false) + } connectTwoWayBeatCounters( status = vol_ognt_counter, @@ -318,7 +337,7 @@ trait EmitsVoluntaryReleases extends HasVoluntaryReleaseMetadataBuffer { trackUp = (r: Release) => r.isVoluntary() && r.requiresAck(), trackDown = (g: Grant) => g.isVoluntary()) - io.outer.release.valid := Mux(buffering, + io.outer.release.valid := !block_orel && Mux(buffering, (state === s_busy) && Mux(io.orel().hasData(), pending_orel_data(vol_ognt_counter.up.idx), pending_orel_send),