A permission on a position in a tree, not a MESI letter. This lesson uses the SiFive TileLink Specification, version 1.8.1 (27 January 2020), chapters 1, 2, 5 and 9. The specification calls the requesting side of a link the master interface and the managing side the slave interface. On the course model, C0 and C1 are masters and H is the slave that manages X.
Level | Adds | Channels |
|---|---|---|
TL-UL (Uncached Lightweight) | Single-beat Get and Put (read and write) | A and D |
TL-UH (Uncached Heavyweight) | Multibeat bursts, atomics (ArithmeticData, LogicalData) and hints (Intent) | A and D |
TL-C (Cached) | Cache block transfers: Acquire, Probe, Release | A, B, C, D and E |
Only TL-C keeps cached copies coherent. A TL-UL device such as a timer never caches, so it needs no B, C or E channel. A TL-C agent talking to a TL-UL device must either avoid the advanced features or sit behind an adapter (section 1.1).
Channel | Direction | TL-C use | Course analogue |
|---|---|---|---|
A | Master to slave | Acquire: ask for permission and usually data | Request (GetS, GetM) |
B | Slave to master | Probe: take permission away, possibly fetch data | Forward (Inv, Fwd-GetS, Fwd-GetM) |
C | Master to slave | ProbeAck answers a Probe. Release is a voluntary writeback. | Inv-Ack or Data to H. PutS, PutE, PutM |
D | Slave to master | Grant gives permission and data. ReleaseAck acknowledges a Release. | Data to the requester. Put-Ack |
E | Master to slave | GrantAck: the final acknowledgement of a Grant | The completion message of Part 4 |
Section 2.2 fixes the priority A < B < C < D < E and says it must be strictly enforced. Section 5 turns it into forward-progress rules: an agent must eventually accept a presented beat and eventually answer a received request, unless it has a higher-priority message in flight or unanswered. So an agent may block a lower channel while it waits on a higher one, never the other way round. Section 9.2 adds that higher-priority messages must be able to bypass lower-priority ones in the network, even to the same agent.
This is the request < forward < response rule with one more class. Every response travels on a higher channel than its request: Acquire (A) is answered by Grant (D), Probe (B) by ProbeAck (C), Release (C) by ReleaseAck (D), and Grant (D) by GrantAck (E). A message that an agent receives can therefore only make it wait for messages above it, and E, at the top, waits for nothing.
Why must E be highest? Section 9.2 says the slave should not issue a Probe for a block while a GrantAck for it is pending. So H holds X's next transaction until GrantAck arrives. If GrantAck could queue behind an Acquire for X on a shared buffer, H would wait for GrantAck, GrantAck would wait for the Acquire, and the Acquire would wait for H: a cycle. Putting GrantAck on the top channel means it always sinks.
For one address, all caching agents form a tree rooted at the slave. Section 9.1 names each node's position. The table also gives the accesses allowed, from Table 29 and the section 9.1 text, and says where the two disagree.
TileLink position | Meaning in the specification | Accesses allowed | Course state |
|---|---|---|---|
None | No cached copy | None | I |
Branch | Copy above the Tip, read-only | Get | S |
Trunk | Copy on the path between the Tip and the root, may be stale. Section 9.1 says it has neither read nor write permission. | None by the 9.1 definition (the copy may be stale). Table 29 of 1.8.1 lists Get, which contradicts 9.1. Do not serve local reads from a Trunk. | No leaf equivalent: an inclusive intermediate cache whose child holds the line |
Tip with Branches | Point of write serialization, copies above it | Get (Table 29). The 9.1 text says read and write, but a store must first Probe the Branches away, after which this is a Tip with no Branches. | On the course model, H (with memory) when C0 and C1 both hold Branch: the root is the Tip (Figure 25). No leaf cache state corresponds. |
Tip, no Branches | Point of memory-access serialization, may hold dirty data | Get, Put, atomics | E or M (MESI, MOESI) |
Three points matter when you read traces. First, Tip covers both E and M: the permission says nothing about dirty data. Exactly as H cannot tell E / 0 from M / 1 in the course (exclusive(C0)), a TileLink home cannot tell a clean Tip from a dirty one until the data comes back. Second, the parameters on a link use only N, B and T. Seen from H across one link, T means the master's subtree holds Trunk-or-Tip: the course's exclusive holder. Third, Trunk appears only in a hierarchy; on the two-cache course model the only caching agents are C0 and C1. A cluster cache inside a two-level directory that has passed exclusive permission up to its core is a Trunk.
Independent settled snapshots, not a sequence. X started at 0; rows with 1 assume C0 stored 1. The last column gives each cache's TileLink permission.
Case | C0 state / value | C1 state / value | H directory | Memory | TileLink C0, C1 |
|---|---|---|---|---|---|
Uncached | I / - | I / - | U | 0 | N, N |
MESI, C0 exclusive clean | E / 0 | I / - | exclusive(C0) | 0 | T, N |
MESI, C0 exclusive dirty | M / 1 | I / - | exclusive(C0) | 0 | T, N |
MSI or MESI, shared | S / 1 | S / 1 | S{C0,C1} | 1 | B, B |
The E and M rows have identical TileLink permissions and identical directory records. The dirty bit lives inside C0's cache, and appears on the wire only when C0 answers a Probe with ProbeAckData or evicts with ReleaseData.
Every TL-C message carries a parameter naming the transition. Section 9.1.4 (Table 31) defines four groups with these 3-bit encodings:
Group | Transitions (encoding) | Meaning | Carried by |
|---|---|---|---|
Grow | NtoB (0), NtoT (1), BtoT (2) | Upgrade, naming old and new permission | AcquireBlock, AcquirePerm |
Prune | TtoB (0), TtoN (1), BtoN (2) | Downgrade, naming old and new permission | ProbeAck, ProbeAckData, Release, ReleaseData |
Report | TtoT (3), BtoB (4), NtoN (5) | No change, reports the current permission | ProbeAck, ProbeAckData, Release, ReleaseData |
Cap | toT (0), toB (1), toN (2) | Target only, old permission not named | ProbeBlock, ProbePerm, Grant, GrantData |
Table 31 calls the downgrade group Prune; the message sections of 9.3 call the same group Shrink. A Probe uses Cap because the home only states a ceiling. Capping above the current permission is allowed and changes nothing, so a toB Probe to a Branch is answered BtoB. A Grant uses Cap and may exceed what the Acquire asked for: an NtoB Acquire answered with a toT Grant is the MESI E grant.
ORDER = "ABCDE"
MSGS = { # message: (channel, possible responses), TileLink 1.8.1 Table 30
"AcquireBlock": ("A", ["Grant", "GrantData"]), "AcquirePerm": ("A", ["Grant"]),
"ProbeBlock": ("B", ["ProbeAck", "ProbeAckData"]), "ProbePerm": ("B", ["ProbeAck"]),
"ProbeAck": ("C", []), "ProbeAckData": ("C", []),
"Release": ("C", ["ReleaseAck"]), "ReleaseData": ("C", ["ReleaseAck"]),
"Grant": ("D", ["GrantAck"]), "GrantData": ("D", ["GrantAck"]),
"ReleaseAck": ("D", []), "GrantAck": ("E", []),
}
def responses_climb(msgs):
return all(ORDER.index(msgs[r][0]) > ORDER.index(ch)
for ch, rs in msgs.values() for r in rs)
assert responses_climb(MSGS)
bad = dict(MSGS, Push=("D", ["PushAck"]), PushAck=("B", []))
assert not responses_climb(bad) # a response below its request breaks the rule
RANK = {"N": 0, "B": 1, "T": 2}
GROW = {"NtoB": 0, "NtoT": 1, "BtoT": 2}
PRUNE = {"TtoB": 0, "TtoN": 1, "BtoN": 2}
REPORT = {"TtoT": 3, "BtoB": 4, "NtoN": 5}
def delta(name):
return RANK[name[3]] - RANK[name[0]]
assert all(delta(n) > 0 for n in GROW)
assert all(delta(n) < 0 for n in PRUNE)
assert all(delta(n) == 0 for n in REPORT)
# ProbeAck and Release put Prune or Report in one field: encodings must not collide
assert not set(PRUNE.values()) & set(REPORT.values())
assert set(GROW.values()) & set(PRUNE.values()) # same codes, so the opcode decides
COURSE = {"I": "N", "S": "B", "E": "T", "M": "T"}
assert [s for s in COURSE if COURSE[s] == "T"] == ["E", "M"] # T cannot say clean or dirty
print("PASS: TileLink responses climb A<B<C<D<E, Prune/Report codes are disjoint, T covers E and M")ProbeAck with BtoB from the Report group. A Cap above or equal to the current permission changes nothing, and C0 holds no dirty data as a Branch, so no ProbeAckData is needed. C0 stays S in course terms.