1
0

tilelink: ToAXI4 - must interlock till last beat

AXI4 makes no guarantee that bursts are handled atomicly.
Thus, you could be part-way through a read burst and suddenly
a write cuts ahead and is visible later, violating FIFO.
This commit is contained in:
Wesley W. Terpstra 2017-05-08 00:00:40 -07:00
parent 8169ba6411
commit 4847c32599

View File

@ -175,16 +175,13 @@ class TLToAXI4(beatBytes: Int, combinational: Boolean = true)(implicit p: Parame
val a_sel = UIntToOH(arw.id, edgeOut.master.endId).toBools val a_sel = UIntToOH(arw.id, edgeOut.master.endId).toBools
val d_sel = UIntToOH(Mux(r_wins, out.r.bits.id, out.b.bits.id), edgeOut.master.endId).toBools val d_sel = UIntToOH(Mux(r_wins, out.r.bits.id, out.b.bits.id), edgeOut.master.endId).toBools
val d_last = Mux(r_wins, out.r.bits.last, Bool(true)) val d_last = Mux(r_wins, out.r.bits.last, Bool(true))
val d_first = RegInit(Bool(true))
when (in.d.fire()) { d_first := d_last }
val stalls = ((a_sel zip d_sel) zip idCount) filter { case (_, n) => n > 1 } map { case ((as, ds), n) => val stalls = ((a_sel zip d_sel) zip idCount) filter { case (_, n) => n > 1 } map { case ((as, ds), n) =>
val count = RegInit(UInt(0, width = log2Ceil(n + 1))) val count = RegInit(UInt(0, width = log2Ceil(n + 1)))
val write = Reg(Bool()) val write = Reg(Bool())
val idle = count === UInt(0) val idle = count === UInt(0)
// Once we start getting the response, it's safe to already switch R/W
val inc = as && out_arw.fire() val inc = as && out_arw.fire()
val dec = ds && d_first && in.d.fire() val dec = ds && d_last && in.d.fire()
count := count + inc.asUInt - dec.asUInt count := count + inc.asUInt - dec.asUInt
assert (!dec || count =/= UInt(0)) // underflow assert (!dec || count =/= UInt(0)) // underflow