axi4 Fragmenter: refine sideband FSM for case of last fragment
This commit is contained in:
parent
19064e602b
commit
8005266131
@ -18,7 +18,7 @@ class AXI4Fragmenter(lite: Boolean = false, maxInFlight: Int = 32, combinational
|
|||||||
def mapSlave(s: AXI4SlaveParameters, beatBytes: Int) = s.copy(
|
def mapSlave(s: AXI4SlaveParameters, beatBytes: Int) = s.copy(
|
||||||
supportsWrite = expandTransfer(s.supportsWrite, beatBytes, s.minAlignment),
|
supportsWrite = expandTransfer(s.supportsWrite, beatBytes, s.minAlignment),
|
||||||
supportsRead = expandTransfer(s.supportsRead, beatBytes, s.minAlignment),
|
supportsRead = expandTransfer(s.supportsRead, beatBytes, s.minAlignment),
|
||||||
interleavedId = if (lite) Some(0) else s.interleavedId) // we preserve interleaving guarantees
|
interleavedId = if (lite) Some(0) else s.interleavedId) // see AXI4FragmenterSideband for !lite case
|
||||||
def mapMaster(m: AXI4MasterParameters) = m.copy(aligned = true)
|
def mapMaster(m: AXI4MasterParameters) = m.copy(aligned = true)
|
||||||
|
|
||||||
val node = AXI4AdapterNode(
|
val node = AXI4AdapterNode(
|
||||||
@ -238,29 +238,46 @@ class AXI4Fragmenter(lite: Boolean = false, maxInFlight: Int = 32, combinational
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We want to put barriers between the fragments of a fragmented transfer and all other transfers.
|
||||||
|
* This lets us use very little state to reassemble the fragments (else we need one FIFO per ID).
|
||||||
|
* Furthermore, because all the fragments share the same AXI ID, they come back contiguously.
|
||||||
|
* This guarantees that no other R responses might get mixed between fragments, ensuring that the
|
||||||
|
* interleavedId for the slaves remains unaffected by the fragmentation transformation.
|
||||||
|
* Of course, if you need to fragment, this means there is a potentially hefty serialization cost.
|
||||||
|
* However, this design allows full concurrency in the common no-fragmentation-needed scenario.
|
||||||
|
*/
|
||||||
class AXI4FragmenterSideband(maxInFlight: Int, flow: Boolean = false) extends Module
|
class AXI4FragmenterSideband(maxInFlight: Int, flow: Boolean = false) extends Module
|
||||||
{
|
{
|
||||||
val io = new QueueIO(Bool(), maxInFlight)
|
val io = new QueueIO(Bool(), maxInFlight)
|
||||||
io.count := UInt(0)
|
io.count := UInt(0)
|
||||||
|
|
||||||
val state = RegInit(Bool(false))
|
val PASS = UInt(2, width = 2) // allow 'last=1' bits to enque, on 'last=0' if count>0 block else accept+FIND
|
||||||
val count = RegInit(UInt(0, width = log2Up(maxInFlight)))
|
val FIND = UInt(0, width = 2) // allow 'last=0' bits to enque, accept 'last=1' and switch to WAIT
|
||||||
val idle = count === UInt(0)
|
val WAIT = UInt(1, width = 2) // block all access till count=0
|
||||||
|
|
||||||
io.deq.bits := state
|
val state = RegInit(PASS)
|
||||||
io.deq.valid := !idle
|
val count = RegInit(UInt(0, width = log2Up(maxInFlight)))
|
||||||
|
val empty = count === UInt(0)
|
||||||
|
val last = count === UInt(1)
|
||||||
|
|
||||||
|
io.deq.bits := state(1) || (last && state(0)) // PASS || (last && WAIT)
|
||||||
|
io.deq.valid := !empty
|
||||||
|
|
||||||
|
io.enq.ready := empty || (state === FIND) || (state === PASS && io.enq.bits)
|
||||||
|
|
||||||
if (flow) {
|
if (flow) {
|
||||||
when (io.enq.valid) {
|
when (io.enq.valid) {
|
||||||
io.deq.valid := Bool(true)
|
io.deq.valid := Bool(true)
|
||||||
when (idle) { io.deq.bits := io.enq.bits }
|
when (empty) { io.deq.bits := io.enq.bits }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
io.enq.ready := idle || (state === io.enq.bits)
|
|
||||||
when (io.enq.fire()) { state := io.enq.bits }
|
|
||||||
|
|
||||||
count := count + io.enq.fire() - io.deq.fire()
|
count := count + io.enq.fire() - io.deq.fire()
|
||||||
|
switch (state) {
|
||||||
|
is(PASS) { when (io.enq.valid && !io.enq.bits && empty) { state := FIND } }
|
||||||
|
is(FIND) { when (io.enq.valid && io.enq.bits) { state := Mux(empty, PASS, WAIT) } }
|
||||||
|
is(WAIT) { when (last && io.deq.ready) { state := PASS } }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object AXI4Fragmenter
|
object AXI4Fragmenter
|
||||||
|
Loading…
Reference in New Issue
Block a user