tilelink: split Acquire into Acquire{Block,Perm} (#1030)
We had planned for a while to add an 'Overwrite' message which obtains permissions without requiring retrieval of data. This is useful whenever a master knows it will completely replace the contents of a cache block. Instead of calling it Overwrite, we decided to split the Acquire type. If you AcquirePerm, you MUST Release and ProbeAck with Data.
This commit is contained in:
parent
81b9ac42a3
commit
bd045a3b95
@ -384,7 +384,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
|
|||||||
val a_size = mtSize(s2_req.typ)
|
val a_size = mtSize(s2_req.typ)
|
||||||
val a_data = Fill(beatWords, pstore1_data)
|
val a_data = Fill(beatWords, pstore1_data)
|
||||||
val acquire = if (edge.manager.anySupportAcquireB) {
|
val acquire = if (edge.manager.anySupportAcquireB) {
|
||||||
edge.Acquire(UInt(0), acquire_address, lgCacheBlockBytes, s2_grow_param)._2 // Cacheability checked by tlb
|
edge.AcquireBlock(UInt(0), acquire_address, lgCacheBlockBytes, s2_grow_param)._2 // Cacheability checked by tlb
|
||||||
} else {
|
} else {
|
||||||
Wire(new TLBundleA(edge.bundle))
|
Wire(new TLBundleA(edge.bundle))
|
||||||
}
|
}
|
||||||
|
@ -276,7 +276,7 @@ class MSHR(id: Int)(implicit edge: TLEdgeOut, p: Parameters) extends L1HellaCach
|
|||||||
io.wb_req.bits.voluntary := Bool(true)
|
io.wb_req.bits.voluntary := Bool(true)
|
||||||
|
|
||||||
io.mem_acquire.valid := state === s_refill_req && grantackq.io.enq.ready
|
io.mem_acquire.valid := state === s_refill_req && grantackq.io.enq.ready
|
||||||
io.mem_acquire.bits := edge.Acquire(
|
io.mem_acquire.bits := edge.AcquireBlock(
|
||||||
fromSource = UInt(id),
|
fromSource = UInt(id),
|
||||||
toAddress = Cat(io.tag, req_idx) << blockOffBits,
|
toAddress = Cat(io.tag, req_idx) << blockOffBits,
|
||||||
lgSize = lgCacheBlockBytes,
|
lgSize = lgCacheBlockBytes,
|
||||||
|
@ -51,8 +51,8 @@ class Atomics(params: TLBundleParameters) extends Module
|
|||||||
UInt(3), // LogicalData
|
UInt(3), // LogicalData
|
||||||
UInt(0), // Get
|
UInt(0), // Get
|
||||||
UInt(0), // Hint
|
UInt(0), // Hint
|
||||||
UInt(0), // Acquire
|
UInt(0), // AcquireBlock
|
||||||
UInt(0)))( // Overwrite
|
UInt(0)))( // AcquirePerm
|
||||||
io.a.opcode))
|
io.a.opcode))
|
||||||
|
|
||||||
// Only the masked bytes can be modified
|
// Only the masked bytes can be modified
|
||||||
|
@ -176,6 +176,11 @@ class TLBroadcast(lineBytes: Int, numTrackers: Int = 4, bufferless: Boolean = fa
|
|||||||
t.probe := (if (caches.size == 0) UInt(0) else Mux(a_cache.orR(), UInt(caches.size-1), UInt(caches.size)))
|
t.probe := (if (caches.size == 0) UInt(0) else Mux(a_cache.orR(), UInt(caches.size-1), UInt(caches.size)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val acq_perms = MuxLookup(in.a.bits.param, Wire(UInt(width = 2)), Array(
|
||||||
|
TLPermissions.NtoB -> TLPermissions.toB,
|
||||||
|
TLPermissions.NtoT -> TLPermissions.toN,
|
||||||
|
TLPermissions.BtoT -> TLPermissions.toN))
|
||||||
|
|
||||||
when (in.a.fire() && a_first) {
|
when (in.a.fire() && a_first) {
|
||||||
probe_todo := ~a_cache // probe all but the cache who poked us
|
probe_todo := ~a_cache // probe all but the cache who poked us
|
||||||
probe_line := in.a.bits.address >> lineShift
|
probe_line := in.a.bits.address >> lineShift
|
||||||
@ -188,10 +193,8 @@ class TLBroadcast(lineBytes: Int, numTrackers: Int = 4, bufferless: Boolean = fa
|
|||||||
TLMessages.Hint -> MuxLookup(in.a.bits.param, Wire(UInt(width = 2)), Array(
|
TLMessages.Hint -> MuxLookup(in.a.bits.param, Wire(UInt(width = 2)), Array(
|
||||||
TLHints.PREFETCH_READ -> TLPermissions.toB,
|
TLHints.PREFETCH_READ -> TLPermissions.toB,
|
||||||
TLHints.PREFETCH_WRITE -> TLPermissions.toN)),
|
TLHints.PREFETCH_WRITE -> TLPermissions.toN)),
|
||||||
TLMessages.Acquire -> MuxLookup(in.a.bits.param, Wire(UInt(width = 2)), Array(
|
TLMessages.AcquireBlock -> acq_perms,
|
||||||
TLPermissions.NtoB -> TLPermissions.toB,
|
TLMessages.AcquirePerm -> acq_perms))
|
||||||
TLPermissions.NtoT -> TLPermissions.toN,
|
|
||||||
TLPermissions.BtoT -> TLPermissions.toN))))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The outer TL connections may not be cached
|
// The outer TL connections may not be cached
|
||||||
@ -236,7 +239,7 @@ class TLBroadcastTracker(id: Int, lineBytes: Int, probeCountBits: Int, bufferles
|
|||||||
when (io.in_a.fire() && io.in_a_first) {
|
when (io.in_a.fire() && io.in_a_first) {
|
||||||
assert (idle)
|
assert (idle)
|
||||||
sent_d := Bool(false)
|
sent_d := Bool(false)
|
||||||
got_e := io.in_a.bits.opcode =/= TLMessages.Acquire
|
got_e := io.in_a.bits.opcode =/= TLMessages.AcquireBlock && io.in_a.bits.opcode =/= TLMessages.AcquirePerm
|
||||||
opcode := io.in_a.bits.opcode
|
opcode := io.in_a.bits.opcode
|
||||||
param := io.in_a.bits.param
|
param := io.in_a.bits.param
|
||||||
size := io.in_a.bits.size
|
size := io.in_a.bits.size
|
||||||
@ -271,7 +274,7 @@ class TLBroadcastTracker(id: Int, lineBytes: Int, probeCountBits: Int, bufferles
|
|||||||
i_data.bits.data := io.in_a.bits.data
|
i_data.bits.data := io.in_a.bits.data
|
||||||
|
|
||||||
val probe_done = count === UInt(0)
|
val probe_done = count === UInt(0)
|
||||||
val acquire = opcode === TLMessages.Acquire
|
val acquire = opcode === TLMessages.AcquireBlock || opcode === TLMessages.AcquirePerm
|
||||||
|
|
||||||
val transform = MuxLookup(param, Wire(UInt(width = 2)), Array(
|
val transform = MuxLookup(param, Wire(UInt(width = 2)), Array(
|
||||||
TLPermissions.NtoB -> TRANSFORM_B,
|
TLPermissions.NtoB -> TRANSFORM_B,
|
||||||
|
@ -22,7 +22,8 @@ object TLMessages
|
|||||||
def LogicalData = UInt(3) // . . => AccessAckData
|
def LogicalData = UInt(3) // . . => AccessAckData
|
||||||
def Get = UInt(4) // . . => AccessAckData
|
def Get = UInt(4) // . . => AccessAckData
|
||||||
def Hint = UInt(5) // . . => HintAck
|
def Hint = UInt(5) // . . => HintAck
|
||||||
def Acquire = UInt(6) // . => Grant[Data]
|
def AcquireBlock = UInt(6) // . => Grant[Data]
|
||||||
|
def AcquirePerm = UInt(7) // . => Grant[Data]
|
||||||
def Probe = UInt(6) // . => ProbeAck[Data]
|
def Probe = UInt(6) // . => ProbeAck[Data]
|
||||||
def AccessAck = UInt(0) // . .
|
def AccessAck = UInt(0) // . .
|
||||||
def AccessAckData = UInt(1) // . .
|
def AccessAckData = UInt(1) // . .
|
||||||
@ -36,7 +37,7 @@ object TLMessages
|
|||||||
def ReleaseAck = UInt(6) // .
|
def ReleaseAck = UInt(6) // .
|
||||||
def GrantAck = UInt(0) // .
|
def GrantAck = UInt(0) // .
|
||||||
|
|
||||||
def isA(x: UInt) = x <= Acquire
|
def isA(x: UInt) = x <= AcquirePerm
|
||||||
def isB(x: UInt) = x <= Probe
|
def isB(x: UInt) = x <= Probe
|
||||||
def isC(x: UInt) = x <= ReleaseData
|
def isC(x: UInt) = x <= ReleaseData
|
||||||
def isD(x: UInt) = x <= ReleaseAck
|
def isD(x: UInt) = x <= ReleaseAck
|
||||||
|
@ -47,7 +47,8 @@ class TLCacheCork(unsafe: Boolean = false)(implicit p: Parameters) extends LazyM
|
|||||||
val a_a = Wire(out.a)
|
val a_a = Wire(out.a)
|
||||||
val a_d = Wire(in.d)
|
val a_d = Wire(in.d)
|
||||||
val isPut = in.a.bits.opcode === PutFullData || in.a.bits.opcode === PutPartialData
|
val isPut = in.a.bits.opcode === PutFullData || in.a.bits.opcode === PutPartialData
|
||||||
val toD = in.a.bits.opcode === Acquire && in.a.bits.param === TLPermissions.BtoT
|
val toD = (in.a.bits.opcode === AcquireBlock && in.a.bits.param === TLPermissions.BtoT) ||
|
||||||
|
(in.a.bits.opcode === AcquirePerm)
|
||||||
in.a.ready := Mux(toD, a_d.ready, a_a.ready)
|
in.a.ready := Mux(toD, a_d.ready, a_a.ready)
|
||||||
|
|
||||||
a_a.valid := in.a.valid && !toD
|
a_a.valid := in.a.valid && !toD
|
||||||
@ -55,7 +56,7 @@ class TLCacheCork(unsafe: Boolean = false)(implicit p: Parameters) extends LazyM
|
|||||||
a_a.bits.source := in.a.bits.source << 1 | Mux(isPut, UInt(1), UInt(0))
|
a_a.bits.source := in.a.bits.source << 1 | Mux(isPut, UInt(1), UInt(0))
|
||||||
|
|
||||||
// Transform Acquire into Get
|
// Transform Acquire into Get
|
||||||
when (in.a.bits.opcode === Acquire) {
|
when (in.a.bits.opcode === AcquireBlock || in.a.bits.opcode === AcquirePerm) {
|
||||||
a_a.bits.opcode := Get
|
a_a.bits.opcode := Get
|
||||||
a_a.bits.param := UInt(0)
|
a_a.bits.param := UInt(0)
|
||||||
a_a.bits.source := in.a.bits.source << 1 | UInt(1)
|
a_a.bits.source := in.a.bits.source << 1 | UInt(1)
|
||||||
|
@ -271,11 +271,25 @@ class TLEdgeOut(
|
|||||||
extends TLEdge(client, manager, params, sourceInfo)
|
extends TLEdge(client, manager, params, sourceInfo)
|
||||||
{
|
{
|
||||||
// Transfers
|
// Transfers
|
||||||
def Acquire(fromSource: UInt, toAddress: UInt, lgSize: UInt, growPermissions: UInt) = {
|
def AcquireBlock(fromSource: UInt, toAddress: UInt, lgSize: UInt, growPermissions: UInt) = {
|
||||||
require (manager.anySupportAcquireB)
|
require (manager.anySupportAcquireB)
|
||||||
val legal = manager.supportsAcquireBFast(toAddress, lgSize)
|
val legal = manager.supportsAcquireBFast(toAddress, lgSize)
|
||||||
val a = Wire(new TLBundleA(bundle))
|
val a = Wire(new TLBundleA(bundle))
|
||||||
a.opcode := TLMessages.Acquire
|
a.opcode := TLMessages.AcquireBlock
|
||||||
|
a.param := growPermissions
|
||||||
|
a.size := lgSize
|
||||||
|
a.source := fromSource
|
||||||
|
a.address := toAddress
|
||||||
|
a.mask := mask(toAddress, lgSize)
|
||||||
|
a.data := UInt(0)
|
||||||
|
(legal, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
def AcquirePerm(fromSource: UInt, toAddress: UInt, lgSize: UInt, growPermissions: UInt) = {
|
||||||
|
require (manager.anySupportAcquireB)
|
||||||
|
val legal = manager.supportsAcquireBFast(toAddress, lgSize)
|
||||||
|
val a = Wire(new TLBundleA(bundle))
|
||||||
|
a.opcode := TLMessages.AcquirePerm
|
||||||
a.param := growPermissions
|
a.param := growPermissions
|
||||||
a.size := lgSize
|
a.size := lgSize
|
||||||
a.source := fromSource
|
a.source := fromSource
|
||||||
|
@ -37,14 +37,25 @@ class TLMonitor(args: TLMonitorArgs) extends TLMonitorBase(args)
|
|||||||
val is_aligned = edge.isAligned(bundle.address, bundle.size)
|
val is_aligned = edge.isAligned(bundle.address, bundle.size)
|
||||||
val mask = edge.full_mask(bundle)
|
val mask = edge.full_mask(bundle)
|
||||||
|
|
||||||
when (bundle.opcode === TLMessages.Acquire) {
|
when (bundle.opcode === TLMessages.AcquireBlock) {
|
||||||
assert (edge.manager.supportsAcquireBSafe(edge.address(bundle), bundle.size), "'A' channel carries Acquire type unsupported by manager" + extra)
|
assert (edge.manager.supportsAcquireBSafe(edge.address(bundle), bundle.size), "'A' channel carries AcquireBlock type unsupported by manager" + extra)
|
||||||
assert (edge.client.supportsProbe(edge.source(bundle), bundle.size), "'A' channel carries Acquire from a client which does not support Probe" + extra)
|
assert (edge.client.supportsProbe(edge.source(bundle), bundle.size), "'A' channel carries AcquireBlock from a client which does not support Probe" + extra)
|
||||||
assert (source_ok, "'A' channel Acquire carries invalid source ID" + extra)
|
assert (source_ok, "'A' channel AcquireBlock carries invalid source ID" + extra)
|
||||||
assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'A' channel Acquire smaller than a beat" + extra)
|
assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'A' channel AcquireBlock smaller than a beat" + extra)
|
||||||
assert (is_aligned, "'A' channel Acquire address not aligned to size" + extra)
|
assert (is_aligned, "'A' channel AcquireBlock address not aligned to size" + extra)
|
||||||
assert (TLPermissions.isGrow(bundle.param), "'A' channel Acquire carries invalid grow param" + extra)
|
assert (TLPermissions.isGrow(bundle.param), "'A' channel AcquireBlock carries invalid grow param" + extra)
|
||||||
assert (~bundle.mask === UInt(0), "'A' channel Acquire contains invalid mask" + extra)
|
assert (~bundle.mask === UInt(0), "'A' channel AcquireBlock contains invalid mask" + extra)
|
||||||
|
}
|
||||||
|
|
||||||
|
when (bundle.opcode === TLMessages.AcquirePerm) {
|
||||||
|
assert (edge.manager.supportsAcquireBSafe(edge.address(bundle), bundle.size), "'A' channel carries AcquirePerm type unsupported by manager" + extra)
|
||||||
|
assert (edge.client.supportsProbe(edge.source(bundle), bundle.size), "'A' channel carries AcquirePerm from a client which does not support Probe" + extra)
|
||||||
|
assert (source_ok, "'A' channel AcquirePerm carries invalid source ID" + extra)
|
||||||
|
assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'A' channel AcquirePerm smaller than a beat" + extra)
|
||||||
|
assert (is_aligned, "'A' channel AcquirePerm address not aligned to size" + extra)
|
||||||
|
assert (TLPermissions.isGrow(bundle.param), "'A' channel AcquirePerm carries invalid grow param" + extra)
|
||||||
|
assert (bundle.param =/= TLPermissions.NtoB, "'A' channel AcquirePerm requests NtoB" + extra)
|
||||||
|
assert (~bundle.mask === UInt(0), "'A' channel AcquirePerm contains invalid mask" + extra)
|
||||||
}
|
}
|
||||||
|
|
||||||
when (bundle.opcode === TLMessages.Get) {
|
when (bundle.opcode === TLMessages.Get) {
|
||||||
|
@ -116,7 +116,7 @@ class TLRAMModel(log: String = "")(implicit p: Parameters) extends LazyModule
|
|||||||
|
|
||||||
when (a_fire) {
|
when (a_fire) {
|
||||||
// Record the request so we can handle it's response
|
// Record the request so we can handle it's response
|
||||||
assert (a.opcode =/= TLMessages.Acquire)
|
assert (a.opcode =/= TLMessages.AcquireBlock && a.opcode =/= TLMessages.AcquirePerm)
|
||||||
|
|
||||||
// Mark the operation as valid
|
// Mark the operation as valid
|
||||||
valid(a.source) := Bool(true)
|
valid(a.source) := Bool(true)
|
||||||
|
Loading…
Reference in New Issue
Block a user