AMBA CHI · Module 6 · CHI Channels
The Snoop Channel (SNP)
Three channels down; SNP is the fourth — the only one that flows from the Home Node to the requesters. This chapter opens the snoop channel: its packet fields — a snoop opcode, the address, the Home Node as source, a transaction ID, and RetToSrc; the snoop request types — SnpShared, SnpUnique, SnpOnce, and the clean/invalidate variants; and its two defining behaviors. First, home-to-RN routing: the Home Node consults its directory and snoops exactly the holders, by Node ID — targeted, not broadcast. Second, RetToSrc tells the snooped cache whether to return data, so data moves only when needed. This chapter details SNP and completes the four-channel tour. Representative model, not the specification.
Intermediate15 min readAMBA CHISNPSnoopsRetToSrcDirectory
Module 6 · Chapter 6.5 · CHI Channels
Project thread — 6.2–6.4 covered REQ, RSP, and DAT. This chapter takes SNP, the last channel, and closes the four-channel tour. 6.6 looks at the fields they share.
1. Learning Outcomes
By the end of this chapter you should be able to:
- List the key fields of a SNP packet — snoop opcode, Addr, SrcID (the HN), TxnID, RetToSrc.
- Name the snoop request types — SnpShared, SnpClean, SnpUnique, SnpOnce, SnpCleanInvalid.
- Explain why SNP is the only channel that flows Home Node → Requester.
- Describe directory-driven routing: the HN snoops exactly the holders, by Node ID.
- State what RetToSrc controls and why dirty data must be returned regardless.
- Implement a representative snoop data-return decision in SystemVerilog, Verilog-2001, and VHDL.
2. Why Should I Learn This?
SNP is how the Home Node reaches into caches — the channel that makes coherency happen at the requesters. Reading it is how you know what a snoop is asking of a cache: share, invalidate, or peek. And it is the only channel flowing home-to-requester, which shapes how the fabric routes and buffers it.
Its practical subtlety is RetToSrc and dirty data. A snoop can ask for data or not, to avoid needless movement — but a dirty line must return its data whichever way RetToSrc points, or the only current copy is lost. Getting that interaction right is the correctness lesson of this chapter.
3. Key Terms
4. Previous Chapter Connection
Chapters 6.2–6.4 covered REQ (requests, RN→HN), RSP (responses), and DAT (payload). The snoop responses those chapters kept referring to — SnpResp on RSP, SnpRespData on DAT — answer something: the snoop itself.
That snoop travels on SNP, this chapter's subject and the fourth channel. It is the one channel that flows the other way — Home Node to requester — and it is how the directory (Chapters 3.5, 5.3) reaches the exact caches that hold a line. With SNP, the four-channel picture is complete.
5. Core Concept — the home reaching into caches
SNP is the Home Node's channel for querying and changing cached copies.
- The packet. A SNP flit carries the snoop opcode (what to do), the Addr (which line), SrcID (the Home Node), a snoop TxnID (which the snooped cache echoes in its response), and RetToSrc (whether to return data). No payload — snoop data comes back on DAT.
- The snoop request types. SnpShared (become Shared — downgrade), SnpClean (become Shared-Clean), SnpUnique (invalidate — the requester wants exclusive), SnpOnce (read the current value without changing state — for ReadOnce), SnpCleanInvalid (write back dirty, then invalidate), SnpMakeInvalid (invalidate, data discarded). Each maps to a cache-side transition (Chapters 5.1, 5.7).
- Home-to-RN routing. SNP is the only channel flowing Home Node → Requester. The HN consults its directory, finds exactly which caches hold the line, and sends a SNP to each of those by Node ID — targeted, not broadcast (Chapters 3.5, 5.3).
- RetToSrc — data only when needed. The RetToSrc field tells the snooped cache whether to return the line's data (SnpRespData on DAT) or only its state (SnpResp on RSP). This avoids moving data the Home Node does not need — but a dirty line must return its data regardless, or the current value is lost.
The synthesis:
SNP is the home reaching into caches — the one channel that flows Home-to-RN, carrying a snoop opcode (share / invalidate / clean / peek) to exactly the holders the directory names. RetToSrc trims data movement to what is needed, with one hard exception: a dirty line always returns its data. Read SNP to know what the home is asking of a cache, and to whom.
6. Engineering Mental Model — the registrar's callbacks
Return to the registrar (the Home Node). REQ was citizens filing requests; SNP is the registrar's callbacks to the people who hold copies.
- The registrar checks the ledger (directory) to see exactly who holds a record, and rings only those people (targeted, by name) — never a mass announcement.
- Each call carries an instruction: "make your copy read-only" (SnpShared), "return and destroy yours" (SnpUnique), "just tell me the current value" (SnpOnce).
- The registrar also says whether it needs the document back (RetToSrc) — to save effort, it often only needs a status. But if the person's copy is marked up (dirty), they must hand it back regardless, because theirs is the only up-to-date version and it cannot be lost.
Targeted callbacks with per-call instructions, and a rule that marked-up copies always come back — that is SNP.
7. Engineering Diagram — the SNP packet
Five fields, no payload. The opcode says what to do; Addr says to which line; SrcID/TxnID tie the response back to the home; RetToSrc says whether to send data.
8. Snoop Request Types
The opcode tells the cache what to do with its copy. A representative set, mapped to the cache-side effect:
| Snoop | Asks the cache to | Cache effect |
|---|---|---|
| SnpShared | become Shared | Unique → Shared (downgrade) |
| SnpClean | become Shared-Clean | clean + downgrade |
| SnpUnique | give up the line | any → Invalid (requester wants exclusive) |
| SnpOnce | reveal the value, keep your state | no state change (for ReadOnce) |
| SnpCleanInvalid | write back dirty, then invalidate | dirty → memory, then Invalid |
| SnpMakeInvalid | invalidate, data discarded | any → Invalid, no data |
Two facts to carry: the snoop opcode selects the cache's transition (Chapters 5.1, 5.7), and SnpOnce is special — it reads the current value without changing the cache's state, exactly what a cacheless ReadOnce needs (Chapter 5.2). The home picks the snoop that matches the requester's intent.
9. Home-to-RN Routing and RetToSrc
Two behaviors set SNP apart from the other channels.
- It flows home-to-requester, targeted. SNP is the only channel from the Home Node to a Request Node. The HN reads its directory, learns exactly which caches hold the line, and sends a SNP to each by Node ID. No broadcast — only the actual holders are snooped (the directory payoff, Chapters 3.5, 5.3).
- RetToSrc trims data movement. The RetToSrc field tells the snooped cache whether to return the line's data. If the home already has the data (or memory is current and clean), it sets RetToSrc = 0 and the cache replies SnpResp only (state, no data). If it needs the data, RetToSrc = 1 and the cache replies SnpRespData.
- The dirty exception. RetToSrc is an optimization for clean lines. A dirty line holds the only current value, so a snoop that removes or downgrades it must return that data — regardless of RetToSrc — or the value is lost.
The point to carry:
The home snoops only the holders (directory-driven, Node-ID routed), and asks for data only when needed (RetToSrc) — two efficiencies. But the one non-negotiable: a dirty line always returns its data on a removing/downgrading snoop, because it is the sole current copy. RetToSrc controls clean data movement; dirty data is never optional.
10. The Snoop Handshake
A snoop of a dirty line shows SNP with its RSP/DAT responses.
A snoop: SnpShared out, SnpResp + SnpRespData back
6 cyclesThe snoop went out on SNP; the response came back on RSP (state) and DAT (the dirty data). Had the line been clean with RetToSrc = 0, there would be a SnpResp on RSP and no DAT beat.
11. RTL / Hardware View — the snoop data-return decision
The cache-side rule for returning data: supply it when the snoop asks (RetToSrc) or when the line is dirty (must not be lost). Here is that decision. Representative and combinational.
// Representative snoop data-return decision, RN side (educational).
// A snooped cache returns data (SnpRespData on DAT) when the snoop's RetToSrc
// requests it, OR when the line is DIRTY (its data is the only current copy and
// must not be lost). Otherwise it returns SnpResp only. A snoop always responds.
module snp_data_return (
input logic dirty, // this cache holds the line dirty (UD/SD)
input logic ret_to_src, // snoop RetToSrc: the requester/home needs the data
output logic send_data, // send SnpRespData on DAT
output logic send_resp // send SnpResp on RSP (always)
);
assign send_data = dirty || ret_to_src; // dirty MUST supply; RetToSrc requests
assign send_resp = 1'b1; // every snoop gets a response
endmoduleThe same behavior in Verilog-2001:
// Representative snoop data-return decision (Verilog-2001).
module snp_data_return (
input dirty, ret_to_src,
output send_data, send_resp
);
assign send_data = dirty | ret_to_src;
assign send_resp = 1'b1;
endmoduleAnd in VHDL:
-- Representative snoop data-return decision (VHDL).
library ieee;
use ieee.std_logic_1164.all;
entity snp_data_return is
port (
dirty, ret_to_src : in std_logic;
send_data, send_resp : out std_logic
);
end entity;
architecture rtl of snp_data_return is
begin
send_data <= dirty or ret_to_src; -- dirty must supply, or RetToSrc requests
send_resp <= '1'; -- every snoop responds
end architecture;All three return data when the line is dirty or RetToSrc is set, and always send a response. The dirty || term is the safety net — it makes dirty data supply even when RetToSrc is 0 — and dropping it is the DebugLab.
12. Verification View — dirty always supplies; clean follows RetToSrc
Two properties: a dirty line always returns data, and every snoop gets a response.
// Bind to snp_data_return.
// 1. A dirty line always returns its data — regardless of RetToSrc.
property p_dirty_supplies;
@(*) dirty |-> send_data;
endproperty
// 2. A clean line returns data iff RetToSrc requests it.
property p_clean_follows_rettosrc;
@(*) (!dirty) |-> (send_data == ret_to_src);
endpropertyThe system point, beyond the two checks:
RetToSrc is an optimization, not a licence to drop data. Its purpose is to avoid moving a clean copy the home does not need — clean data is identical to memory, so returning it is often wasteful. But a dirty line is the only place the current value lives, so a snoop that removes or downgrades it must return that data whatever RetToSrc says. Conditioning data return on RetToSrc alone silently loses dirty data — a no-lost-update violation (Chapters 5.1, 5.3). Two rules, both required: clean follows RetToSrc; dirty always supplies.
- What it proves: dirty always supplies; clean follows RetToSrc.
- What it does not prove: the cache's state transition (Chapters 5.1, 5.7).
- Bug signature: dirty data not returned when RetToSrc is 0 — a lost update (the DebugLab).
13. Testbench — data-return across dirty and RetToSrc
Checks the four combinations of dirty and RetToSrc.
module tb_snp_data_return;
logic dirty, ret_to_src, send_data, send_resp;
int errors = 0;
snp_data_return dut (.*);
task automatic check(input logic d, input logic r, input logic exp_data, input string tag);
dirty = d; ret_to_src = r; #1;
if (send_data !== exp_data || send_resp !== 1'b1) begin
errors++; $display("FAIL [%s] send_data=%b send_resp=%b", tag, send_data, send_resp);
end else $display("PASS [%s] send_data=%b", tag, send_data);
endtask
initial begin
check(1'b0, 1'b0, 1'b0, "clean, RetToSrc=0 -> no data");
check(1'b0, 1'b1, 1'b1, "clean, RetToSrc=1 -> data");
check(1'b1, 1'b0, 1'b1, "DIRTY, RetToSrc=0 -> data (must supply)");
check(1'b1, 1'b1, 1'b1, "dirty, RetToSrc=1 -> data");
if (errors == 0) $display("ALL TESTS PASSED");
else $display("%0d FAILURE(S)", errors);
$finish;
end
endmoduleExpected output:
PASS [clean, RetToSrc=0 -> no data] send_data=0
PASS [clean, RetToSrc=1 -> data] send_data=1
PASS [DIRTY, RetToSrc=0 -> data (must supply)] send_data=1
PASS [dirty, RetToSrc=1 -> data] send_data=114. DebugLab — returning data only when RetToSrc is set
Returning data only when RetToSrc is set
DATA RETURN GATED ON RetToSrc ALONE -> DIRTY DATA LOSTA value one core wrote disappears: another core's read of the same line returns the old data, even though the writer had it cached and modified. It only happens for lines that were dirty in a cache and then snooped.
A dirty line snooped with RetToSrc = 0, returning no data:
dirty ret_to_src send_data note
1 0 0 WRONG: dirty line returns no dataThe line was dirty, but because RetToSrc was 0 the cache sent SnpResp only — the modified data was never returned.
The snoop-response computed send_data = ret_to_src — data return conditioned on RetToSrc alone. From a dirty-line snoop with RetToSrc = 0, the dirty data is dropped, and the Home Node has only stale memory to complete with.
RetToSrc governs whether a clean copy is worth returning — clean data equals memory, so it is often skipped. But a dirty line holds the only current value; a snoop that removes or downgrades it must return that data or it is lost. Gating data return on RetToSrc alone forgets the dirty case, so modified data vanishes — the classic no-lost-update violation.
Return data when the line is dirty OR RetToSrc is set: send_data = dirty || ret_to_src. Clean lines follow RetToSrc (the intended optimization); dirty lines always supply their data. Verify "dirty implies send_data" as an invariant so the dirty case can never be optimized away. RetToSrc trims clean-data movement; it never overrides the duty to preserve dirty data.
15. Common Mistakes
- Gating data return on RetToSrc alone. Assumption: RetToSrc decides everything. Bug: dirty data lost (the DebugLab). Prevention: dirty or RetToSrc returns data.
- Broadcasting snoops. Assumption: snoop everyone. Bug: wasted traffic (Chapter 3.5). Prevention: the directory names the holders; snoop only them.
- Wrong snoop type. Assumption: any snoop works. Bug: sharing when you meant to invalidate. Prevention: SnpShared downgrades, SnpUnique invalidates, SnpOnce peeks.
- Snooping the wrong direction. Assumption: snoops can flow any way. Bug: mis-routed. Prevention: SNP is Home Node → Requester only.
- Ignoring SnpOnce's no-change rule. Assumption: every snoop changes state. Bug: needlessly downgrading on a peek. Prevention: SnpOnce reads without changing state.
- Losing the response TxnID. Assumption: any correlation works. Bug: mis-matched snoop response. Prevention: echo the snoop's TxnID in SnpResp.
16. Engineering Checklist
- Route SNP Home Node → Requester, to the directory's holders by Node ID.
- Select the snoop opcode by intent (SnpShared / SnpUnique / SnpClean / SnpOnce).
- Return data when the line is dirty OR RetToSrc is set.
- Never drop dirty data on a removing/downgrading snoop.
- Keep SnpOnce state-preserving (a peek).
- Echo the snoop's TxnID in the SnpResp / SnpRespData.
17. Key Takeaways
- SNP is the only channel that flows Home Node → Requester — the home reaching into caches.
- Its fields: snoop opcode, Addr, SrcID (the HN), TxnID, RetToSrc.
- Snoop types select the cache's transition: SnpShared (downgrade), SnpUnique (invalidate), SnpOnce (peek), and clean/invalidate variants.
- The home snoops only the directory's holders, by Node ID — targeted, not broadcast.
- RetToSrc trims clean-data movement; a dirty line always returns its data regardless.
- Gating data return on RetToSrc alone loses dirty data; the model here is representative.
18. Quick Revision
The SNP channel. The only channel flowing Home Node → Requester — the home reaching into caches. Fields: snoop opcode, Addr, SrcID (the HN), snoop TxnID (echoed in the response), RetToSrc. Snoop types map to cache transitions: SnpShared (downgrade to Shared), SnpClean, SnpUnique (invalidate), SnpOnce (read without changing state — for ReadOnce), SnpCleanInvalid, SnpMakeInvalid. Routing is directory-driven: the HN snoops only the holders, by Node ID (targeted, not broadcast). RetToSrc says whether the cache returns data — an optimization for clean lines (clean data equals memory) — but a dirty line always returns its data (dirty OR RetToSrc), or the only current value is lost. The response is SnpResp (RSP) plus SnpRespData (DAT) when data is returned. Representative model; 6.6 covers packet common fields.
Coming Next
Chapter 6.6 — Packet Common Fields. The four channels are covered; the next chapter steps back to what they share. Several fields recur across REQ, RSP, DAT, and SNP — the TxnID that ties a transaction together, the Node IDs (SrcID/TgtID) the fabric routes on, and the Opcode that names each message. Chapter 6.6 details these common fields once, so you can read any packet on any channel by recognizing the shared skeleton beneath its channel-specific payload.