tilelink2: Fragmenter now supports early Ack
This commit is contained in:
parent
e09fa866b7
commit
6ee69454c3
@ -14,7 +14,7 @@ import scala.math.{min,max}
|
|||||||
// Fragmenter modifies: PutFull, PutPartial, LogicalData, Get, Hint
|
// Fragmenter modifies: PutFull, PutPartial, LogicalData, Get, Hint
|
||||||
// Fragmenter passes: ArithmeticData (truncated to minSize if alwaysMin)
|
// Fragmenter passes: ArithmeticData (truncated to minSize if alwaysMin)
|
||||||
// Fragmenter cannot modify acquire (could livelock); thus it is unsafe to put caches on both sides
|
// Fragmenter cannot modify acquire (could livelock); thus it is unsafe to put caches on both sides
|
||||||
class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean = false)(implicit p: Parameters) extends LazyModule
|
class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean = false, val earlyAck: Boolean = false)(implicit p: Parameters) extends LazyModule
|
||||||
{
|
{
|
||||||
require (isPow2 (maxSize))
|
require (isPow2 (maxSize))
|
||||||
require (isPow2 (minSize))
|
require (isPow2 (minSize))
|
||||||
@ -137,6 +137,7 @@ class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean =
|
|||||||
val dOrig = Reg(UInt())
|
val dOrig = Reg(UInt())
|
||||||
val dFragnum = out.d.bits.source(fragmentBits-1, 0)
|
val dFragnum = out.d.bits.source(fragmentBits-1, 0)
|
||||||
val dFirst = acknum === UInt(0)
|
val dFirst = acknum === UInt(0)
|
||||||
|
val dLast = dFragnum === UInt(0)
|
||||||
val dsizeOH = UIntToOH (out.d.bits.size, log2Ceil(maxDownSize)+1)
|
val dsizeOH = UIntToOH (out.d.bits.size, log2Ceil(maxDownSize)+1)
|
||||||
val dsizeOH1 = UIntToOH1(out.d.bits.size, log2Up(maxDownSize))
|
val dsizeOH1 = UIntToOH1(out.d.bits.size, log2Up(maxDownSize))
|
||||||
val dHasData = edgeOut.hasData(out.d.bits)
|
val dHasData = edgeOut.hasData(out.d.bits)
|
||||||
@ -156,7 +157,7 @@ class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean =
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Swallow up non-data ack fragments
|
// Swallow up non-data ack fragments
|
||||||
val drop = !dHasData && (dFragnum =/= UInt(0))
|
val drop = !dHasData && !(if (earlyAck) dFirst else dLast)
|
||||||
out.d.ready := in.d.ready || drop
|
out.d.ready := in.d.ready || drop
|
||||||
in.d.valid := out.d.valid && !drop
|
in.d.valid := out.d.valid && !drop
|
||||||
in.d.bits := out.d.bits // pass most stuff unchanged
|
in.d.bits := out.d.bits // pass most stuff unchanged
|
||||||
@ -164,11 +165,18 @@ class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean =
|
|||||||
in.d.bits.source := out.d.bits.source >> fragmentBits
|
in.d.bits.source := out.d.bits.source >> fragmentBits
|
||||||
in.d.bits.size := Mux(dFirst, dFirst_size, dOrig)
|
in.d.bits.size := Mux(dFirst, dFirst_size, dOrig)
|
||||||
|
|
||||||
// Combine the error flag
|
if (earlyAck) {
|
||||||
val r_error = RegInit(Bool(false))
|
// If you do early Ack, errors may not be dropped
|
||||||
val d_error = r_error | out.d.bits.error
|
// ... which roughly means: Puts may not fail
|
||||||
when (out.d.fire()) { r_error := Mux(drop, d_error, UInt(0)) }
|
assert (!out.d.bits.error || !drop)
|
||||||
in.d.bits.error := d_error
|
in.d.bits.error := out.d.bits.error
|
||||||
|
} else {
|
||||||
|
// Combine the error flag
|
||||||
|
val r_error = RegInit(Bool(false))
|
||||||
|
val d_error = r_error | out.d.bits.error
|
||||||
|
when (out.d.fire()) { r_error := Mux(drop, d_error, UInt(0)) }
|
||||||
|
in.d.bits.error := d_error
|
||||||
|
}
|
||||||
|
|
||||||
// What maximum transfer sizes do downstream devices support?
|
// What maximum transfer sizes do downstream devices support?
|
||||||
val maxArithmetics = managers.map(_.supportsArithmetic.max)
|
val maxArithmetics = managers.map(_.supportsArithmetic.max)
|
||||||
@ -252,8 +260,8 @@ class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean =
|
|||||||
object TLFragmenter
|
object TLFragmenter
|
||||||
{
|
{
|
||||||
// applied to the TL source node; y.node := TLFragmenter(x.node, 256, 4)
|
// applied to the TL source node; y.node := TLFragmenter(x.node, 256, 4)
|
||||||
def apply(minSize: Int, maxSize: Int, alwaysMin: Boolean = false)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = {
|
def apply(minSize: Int, maxSize: Int, alwaysMin: Boolean = false, earlyAck: Boolean = false)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = {
|
||||||
val fragmenter = LazyModule(new TLFragmenter(minSize, maxSize, alwaysMin))
|
val fragmenter = LazyModule(new TLFragmenter(minSize, maxSize, alwaysMin, earlyAck))
|
||||||
fragmenter.node := x
|
fragmenter.node := x
|
||||||
fragmenter.node
|
fragmenter.node
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user