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