1
0

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:
Wesley W. Terpstra 2017-10-05 12:49:49 -07:00 committed by GitHub
parent 81b9ac42a3
commit bd045a3b95
9 changed files with 55 additions and 25 deletions

View File

@ -384,7 +384,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
val a_size = mtSize(s2_req.typ)
val a_data = Fill(beatWords, pstore1_data)
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 {
Wire(new TLBundleA(edge.bundle))
}

View File

@ -276,7 +276,7 @@ class MSHR(id: Int)(implicit edge: TLEdgeOut, p: Parameters) extends L1HellaCach
io.wb_req.bits.voluntary := Bool(true)
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),
toAddress = Cat(io.tag, req_idx) << blockOffBits,
lgSize = lgCacheBlockBytes,

View File

@ -51,8 +51,8 @@ class Atomics(params: TLBundleParameters) extends Module
UInt(3), // LogicalData
UInt(0), // Get
UInt(0), // Hint
UInt(0), // Acquire
UInt(0)))( // Overwrite
UInt(0), // AcquireBlock
UInt(0)))( // AcquirePerm
io.a.opcode))
// Only the masked bytes can be modified

View File

@ -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)))
}
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) {
probe_todo := ~a_cache // probe all but the cache who poked us
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(
TLHints.PREFETCH_READ -> TLPermissions.toB,
TLHints.PREFETCH_WRITE -> TLPermissions.toN)),
TLMessages.Acquire -> MuxLookup(in.a.bits.param, Wire(UInt(width = 2)), Array(
TLPermissions.NtoB -> TLPermissions.toB,
TLPermissions.NtoT -> TLPermissions.toN,
TLPermissions.BtoT -> TLPermissions.toN))))
TLMessages.AcquireBlock -> acq_perms,
TLMessages.AcquirePerm -> acq_perms))
}
// 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) {
assert (idle)
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
param := io.in_a.bits.param
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
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(
TLPermissions.NtoB -> TRANSFORM_B,

View File

@ -22,7 +22,8 @@ object TLMessages
def LogicalData = UInt(3) // . . => AccessAckData
def Get = UInt(4) // . . => AccessAckData
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 AccessAck = UInt(0) // . .
def AccessAckData = UInt(1) // . .
@ -36,7 +37,7 @@ object TLMessages
def ReleaseAck = UInt(6) // .
def GrantAck = UInt(0) // .
def isA(x: UInt) = x <= Acquire
def isA(x: UInt) = x <= AcquirePerm
def isB(x: UInt) = x <= Probe
def isC(x: UInt) = x <= ReleaseData
def isD(x: UInt) = x <= ReleaseAck

View File

@ -47,7 +47,8 @@ class TLCacheCork(unsafe: Boolean = false)(implicit p: Parameters) extends LazyM
val a_a = Wire(out.a)
val a_d = Wire(in.d)
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)
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))
// 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.param := UInt(0)
a_a.bits.source := in.a.bits.source << 1 | UInt(1)

View File

@ -271,11 +271,25 @@ class TLEdgeOut(
extends TLEdge(client, manager, params, sourceInfo)
{
// Transfers
def Acquire(fromSource: UInt, toAddress: UInt, lgSize: UInt, growPermissions: UInt) = {
def AcquireBlock(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.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.size := lgSize
a.source := fromSource

View File

@ -37,14 +37,25 @@ class TLMonitor(args: TLMonitorArgs) extends TLMonitorBase(args)
val is_aligned = edge.isAligned(bundle.address, bundle.size)
val mask = edge.full_mask(bundle)
when (bundle.opcode === TLMessages.Acquire) {
assert (edge.manager.supportsAcquireBSafe(edge.address(bundle), bundle.size), "'A' channel carries Acquire 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 (source_ok, "'A' channel Acquire carries invalid source ID" + extra)
assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'A' channel Acquire smaller than a beat" + extra)
assert (is_aligned, "'A' channel Acquire address not aligned to size" + extra)
assert (TLPermissions.isGrow(bundle.param), "'A' channel Acquire carries invalid grow param" + extra)
assert (~bundle.mask === UInt(0), "'A' channel Acquire contains invalid mask" + extra)
when (bundle.opcode === TLMessages.AcquireBlock) {
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 AcquireBlock from a client which does not support Probe" + extra)
assert (source_ok, "'A' channel AcquireBlock carries invalid source ID" + extra)
assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'A' channel AcquireBlock smaller than a beat" + extra)
assert (is_aligned, "'A' channel AcquireBlock address not aligned to size" + extra)
assert (TLPermissions.isGrow(bundle.param), "'A' channel AcquireBlock carries invalid grow param" + 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) {

View File

@ -116,7 +116,7 @@ class TLRAMModel(log: String = "")(implicit p: Parameters) extends LazyModule
when (a_fire) {
// 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
valid(a.source) := Bool(true)