fix lockup from back to back releases with data
This commit is contained in:
		| @@ -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)  | ||||
|  | ||||
|   | ||||
| @@ -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( | ||||
|   | ||||
| @@ -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 | ||||
|  | ||||
|   | ||||
| @@ -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), | ||||
|   | ||||
		Reference in New Issue
	
	Block a user