Skip to content

AMBA CHI · Module 9 · Snoop Flows

Snoop Request Types

Chapter 9.1 said why snoops exist; this one names which snoops there are. Every snoop opcode is defined by two things: the state it forces in the snooped cache, and whether it needs that cache's data back. Those two axes generate the whole catalogue. SnpShared and SnpClean downgrade a holder to Shared Clean; SnpUnique, SnpCleanInvalid, and SnpMakeInvalid invalidate it; SnpOnce takes a snapshot without changing its state. On data, most return the line only if the holder had it dirty, SnpMakeInvalid never, and SnpOnce always. The request opcode decides which snoop the home sends. The sharp edge is the data axis: an invalidating snoop that forgets to collect dirty data destroys it. Representative model, not the specification.

Intermediate16 min readAMBA CHISnoop TypesSnpUniqueSnpMakeInvalidCoherency

Module 9 · Chapter 9.2 · Snoop Flows

Project thread — 9.1 established why snoops exist. This chapter catalogues the snoop opcodes; 9.3 covers the responses they produce.

1. Learning Outcomes

By the end of this chapter you should be able to:

  • Name the main snoop request types — SnpShared, SnpClean, SnpUnique, SnpCleanInvalid, SnpMakeInvalid, SnpOnce.
  • Organize them on two axes: the state forced and the data requirement.
  • Match each snoop to the request flow that issues it.
  • Distinguish invalidating snoops from downgrading snoops, and data-returning from data-free.
  • Diagnose why a no-data invalidating snoop can destroy dirty data.
  • Implement a representative snoop decoder in SystemVerilog, Verilog-2001, and VHDL.

2. Why Should I Learn This?

The snoop types are the vocabulary of the whole coherence protocol. Every request flow in Module 8 issued one of them, and the rest of Module 9 traces their responses, their data transfers, their ownership moves. Once you can place any snoop on the two axes — what state does it leave the holder in, and does it need the data — every flow that uses it becomes predictable.

More than a naming exercise, it is where the subtle coherence bugs are chosen. Pick a snoop that forces the wrong state and you leave a stale sharer or over-invalidate; pick one that skips the data when the data was needed and you silently destroy a modification. The request opcode dictates the snoop, so understanding the catalogue is understanding how a core's intent becomes a precise, correct action inside another core's cache.

3. Key Terms

4. Previous Chapter Connection

Chapter 9.1 gave the two reasons snoops exist — invalidate for exclusivity, fetch dirty data. This chapter turns those reasons into a named set. Each snoop opcode is a specific combination: a target state (for the exclusivity/sharing reason) and a data rule (for the fetch reason).

You have met most of them already, one per flow: SnpShared in ReadShared (8.1), SnpUnique in ReadUnique (8.2), SnpClean in ReadClean (8.3), SnpNotSharedDirty in ReadNotSharedDirty (8.4), SnpCleanInvalid in WriteUnique (8.5), SnpMakeInvalid in MakeUnique (8.8). This chapter collects them into one table and shows the structure behind them — so they stop being a list to memorize and become two axes to reason with.

5. Core Concept — a snoop is a forced state plus a data rule

Every snoop opcode is fully described by two choices: what state it leaves the holder in, and whether it takes the holder's data. The catalogue is the cross-product.

  • Downgrading snoops → SC. SnpShared and SnpClean reduce a holder to Shared Clean — it keeps a readable copy. Data comes back only if the holder was dirty.
  • Invalidating snoops → I. SnpUnique, SnpCleanInvalid, and SnpMakeInvalid clear the holder to Invalid. They differ on data: SnpUnique forwards dirty data to the requester, SnpCleanInvalid writes dirty data back to memory, SnpMakeInvalid takes no data at all.
  • Snapshot snoop → unchanged. SnpOnce returns a copy of the line without changing the holder's state — a read that peeks.
  • Ownership-preserving snoop. SnpNotSharedDirty lets the holder keep SD (dirty ownership) while forwarding a clean copy (Chapter 8.4).

The rule tying it together: the request opcode chooses the snoop. A ReadShared needs sharers to survive, so it issues SnpShared; a ReadUnique needs them gone, so it issues SnpUnique; a MakeUnique already has the data, so it issues the no-data SnpMakeInvalid.

The synthesis:

A snoop type is a forced state (SC / I / unchanged) paired with a data rule (if-dirty / forward / writeback / never / snapshot). The request opcode selects the pair to match its intent. Get the state wrong and you mis-set the holder; get the data rule wrong — especially a no-data invalidation when the data was needed — and you lose dirty data. The catalogue is those two axes.

6. Engineering Mental Model — kinds of recall notice

Return to the library: the librarian (home) sends different recall notices to a reader (holder), and each notice specifies two things — what the reader does with their copy, and whether they hand pages back.

  • "Share it, read-only" (SnpShared): keep a read-only copy; hand back your marked pages if you annotated them.
  • "Surrender it, I need it" (SnpUnique): give up your copy entirely; hand over your annotations so the next reader gets them.
  • "Surrender it, memory's copy is fine" (SnpMakeInvalid): give up your copy — and I need no pages, because a fresh version is coming.
  • "Let me glance at it" (SnpOnce): show me a copy; keep yours exactly as it is.

Same messenger, different instructions. The two variables are always: what happens to your copy, and do you return your pages. Send "surrender, no pages needed" to someone holding the only annotated version, and their annotations are lost — the bug at the end of this chapter.

7. Engineering Diagram — a snoop request and its response

A representative snoop exchange. The Home Node sends a SNP SnpUnique to holder RN1. RN1 applies the forced state, transitioning from Unique Dirty to Invalid, and returns a RSP SnpResp reporting the outcome plus a DAT SnpRespData carrying the dirty data. The snoop opcode determines both the forced state and whether data is returned.Snoop exchange — the opcode carries state and data rulesHN · home (issues snoop)RN1 · holder (UD)SNP: SnpUnique(force I)RSP: SnpResp (now I)DAT: SnpRespData(dirty forwarded)
Figure 1 — a representative snoop exchange. The Home Node sends a snoop opcode (here SnpUnique) to holder RN1; RN1 applies the forced state (Invalid) and, because it held the line dirty, returns both a response and the data. The opcode carries both the forced state and the data rule; a different opcode would force a different state or skip the data. The two axes are visible in one exchange.

One exchange, two axes: the opcode SnpUnique forced the state to I, and because the line was dirty it also returned SnpRespData. Swap in SnpShared and the state would be SC; swap in SnpMakeInvalid and no data would come back at all.

8. The Snoop Request Types

The catalogue, each row a (state, data) pair.

Snoop opcodeForces holder toData returnedIssued by
SnpSharedSC (keeps shared)if dirtyReadShared
SnpCleanSC (clean)if dirty (writeback)ReadClean
SnpNotSharedDirtyholder keeps SDif dirty (owner retained)ReadNotSharedDirty
SnpUniqueIif dirty (forwarded)ReadUnique
SnpCleanInvalidI (memory clean)if dirty (writeback)WriteUnique
SnpMakeInvalidIneverMakeUnique, full writes
SnpOnceunchangeda copyReadOnce

The rule to carry: read the table as two columns of meaning — the forced state (does the holder keep a copy, lose it, or stay put) and the data rule (does the line come back). The right-hand column names the flow, so in practice you rarely choose a snoop directly; the request opcode chooses it. But knowing the pairing lets you verify that a flow's snoop matches its intent.

9. The Two Axes — forced state × data requirement

Naming the axes explicitly makes the whole set memorable.

  • Axis 1 — forced state. Downgrade (→ SC): SnpShared, SnpClean. Invalidate (→ I): SnpUnique, SnpCleanInvalid, SnpMakeInvalid. Unchanged: SnpOnce. Ownership-preserving (holder stays SD): SnpNotSharedDirty.
  • Axis 2 — data requirement. If dirty: most snoops return the line only when the holder had it dirty. Never: SnpMakeInvalid takes no data. Always: SnpOnce takes a copy regardless.
  • The pairing is the point. The state axis serves the exclusivity/sharing reason; the data axis serves the fetch-the-latest reason. A snoop is one choice on each.
  • Where data comes back, it goes somewhere. SnpUnique forwards it to the requester; SnpCleanInvalid / SnpClean write it back to memory. Same "returns data if dirty," different destination.

The point to carry:

Two independent axes generate the catalogue: what state to leave the holder in, and whether to take its data. Every snoop is a point in that 2-D space, chosen to match a request's intent. Reasoning on the axes beats memorizing names — given a flow, you can derive its snoop (what must the holder become, and does the requester need the data), and given a snoop, you can state its effect. The axes are also where the bugs live: the wrong state on axis one, or a "never" on axis two when the data was needed.

10. Walkthrough — which snoop each request issues

Trace a holder in UD under three different requests, and watch the snoop change.

  1. ReadShared arrives. The requester wants a shared copy; sharers may survive. The home issues SnpShared → the holder downgrades UD → SC and returns its dirty data (writeback). Holder keeps a readable copy.
  2. ReadUnique arrives. The requester wants sole ownership to write. The home issues SnpUnique → the holder goes UD → I and forwards its dirty data to the requester. No copy survives.
  3. MakeUnique arrives. The requester already holds a valid copy and just needs exclusivity. The home issues SnpMakeInvalid → the holder goes UD → I with no data returned — the requester does not need it.

Same starting holder, three snoops, three outcomes. Note step 3: SnpMakeInvalid was correct only because the requester did not need the data. Issue it when the requester did need the dirty line, and the modification is gone — the DebugLab.

11. RTL / Hardware View — a snoop decoder

The snoop's effect reduces to a decode of the opcode against the holder's state: produce the next state and whether data is returned. Representative — a generalization of the single-snoop handler, covering the catalogue.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Representative snoop decoder (educational).
// Given the snoop opcode and the holder's current state, produce the next state
// and whether the holder returns data. Downgrading snoops -> SC; invalidating ->
// I; SnpOnce leaves the state unchanged. Data returns if dirty, except MakeInvalid
// (never) and SnpOnce (always a copy).
module chi_snoop_decode (
  input  logic [2:0] snp_type,      // SNP_SHARED, SNP_CLEAN, SNP_UNIQUE, SNP_CLEANINVALID, SNP_MAKEINVALID, SNP_ONCE
  input  logic [2:0] cur_state,     // INV, UC, UD, SC, SD
  output logic [2:0] next_state,
  output logic       send_data
);
  localparam logic [2:0] SNP_SHARED=3'd0, SNP_CLEAN=3'd1, SNP_UNIQUE=3'd2,
                         SNP_CLEANINVALID=3'd3, SNP_MAKEINVALID=3'd4, SNP_ONCE=3'd5;
  localparam logic [2:0] INV=3'd0, UC=3'd1, UD=3'd2, SC=3'd3, SD=3'd4;
 
  logic held, dirty;
  assign held  = (cur_state != INV);
  assign dirty = (cur_state == UD) || (cur_state == SD);
 
  always_comb begin
    if (!held) begin
      next_state = INV;  send_data = 1'b0;          // nothing to snoop
    end else begin
      unique case (snp_type)
        SNP_ONCE:         begin next_state = cur_state; send_data = 1'b1;   end // snapshot
        SNP_SHARED,
        SNP_CLEAN:        begin next_state = SC;        send_data = dirty; end // downgrade
        SNP_UNIQUE,
        SNP_CLEANINVALID: begin next_state = INV;       send_data = dirty; end // invalidate + data
        SNP_MAKEINVALID:  begin next_state = INV;       send_data = 1'b0;  end // invalidate, no data
        default:          begin next_state = cur_state; send_data = 1'b0;  end
      endcase
    end
  end
endmodule

The same behavior in Verilog-2001:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Representative snoop decoder (Verilog-2001).
module chi_snoop_decode (
  input  [2:0] snp_type,
  input  [2:0] cur_state,
  output reg [2:0] next_state,
  output reg       send_data
);
  localparam SNP_SHARED=3'd0, SNP_CLEAN=3'd1, SNP_UNIQUE=3'd2,
             SNP_CLEANINVALID=3'd3, SNP_MAKEINVALID=3'd4, SNP_ONCE=3'd5;
  localparam INV=3'd0, UC=3'd1, UD=3'd2, SC=3'd3, SD=3'd4;
 
  wire held  = (cur_state != INV);
  wire dirty = (cur_state == UD) || (cur_state == SD);
 
  always @* begin
    if (!held) begin
      next_state = INV;  send_data = 1'b0;
    end else begin
      case (snp_type)
        SNP_ONCE:         begin next_state = cur_state; send_data = 1'b1;  end
        SNP_SHARED,
        SNP_CLEAN:        begin next_state = SC;        send_data = dirty; end
        SNP_UNIQUE,
        SNP_CLEANINVALID: begin next_state = INV;       send_data = dirty; end
        SNP_MAKEINVALID:  begin next_state = INV;       send_data = 1'b0;  end
        default:          begin next_state = cur_state; send_data = 1'b0;  end
      endcase
    end
  end
endmodule

And in VHDL:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-- Representative snoop decoder (VHDL).
library ieee;
use ieee.std_logic_1164.all;
 
entity chi_snoop_decode is
  port (
    snp_type   : in  std_logic_vector(2 downto 0);
    cur_state  : in  std_logic_vector(2 downto 0);
    next_state : out std_logic_vector(2 downto 0);
    send_data  : out std_logic
  );
end entity;
 
architecture rtl of chi_snoop_decode is
  constant SNP_UNIQUE       : std_logic_vector(2 downto 0) := "010";
  constant SNP_CLEANINVALID : std_logic_vector(2 downto 0) := "011";
  constant SNP_MAKEINVALID  : std_logic_vector(2 downto 0) := "100";
  constant SNP_ONCE         : std_logic_vector(2 downto 0) := "101";
  constant INV : std_logic_vector(2 downto 0) := "000";
  constant SC  : std_logic_vector(2 downto 0) := "011";
  signal held, dirty : boolean;
begin
  held  <= (cur_state /= INV);
  dirty <= (cur_state = "010") or (cur_state = "100");  -- UD or SD
 
  process (snp_type, cur_state, held, dirty)
  begin
    if not held then
      next_state <= INV;  send_data <= '0';
    elsif snp_type = SNP_ONCE then
      next_state <= cur_state;  send_data <= '1';                    -- snapshot
    elsif snp_type = SNP_UNIQUE or snp_type = SNP_CLEANINVALID then
      next_state <= INV;        send_data <= '1' when dirty else '0'; -- invalidate + data
    elsif snp_type = SNP_MAKEINVALID then
      next_state <= INV;        send_data <= '0';                    -- invalidate, no data
    else  -- SnpShared / SnpClean
      next_state <= SC;         send_data <= '1' when dirty else '0'; -- downgrade
    end if;
  end process;
end architecture;

All three map downgrading snoops to SC, invalidating snoops to I, and SnpOnce to unchanged, with the data rule per opcode — SnpMakeInvalid uniquely returns no data. The DebugLab shows what that "no data" costs when the data was needed.

12. Verification View — the axes as properties

The properties that pin the two axes: invalidating snoops reach I, downgrading snoops reach SC, and MakeInvalid never returns data.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Bind to chi_snoop_decode.
// 1. Invalidating snoops leave a held holder in Invalid.
property p_invalidating_to_inv;
  @(*) ((snp_type == 3'd2 /*UNIQUE*/) || (snp_type == 3'd3 /*CLEANINVALID*/) ||
        (snp_type == 3'd4 /*MAKEINVALID*/)) && (cur_state != 3'd0 /*INV*/)
       |-> (next_state == 3'd0 /*INV*/);
endproperty
 
// 2. Downgrading snoops leave a held holder in Shared Clean.
property p_downgrading_to_sc;
  @(*) ((snp_type == 3'd0 /*SHARED*/) || (snp_type == 3'd1 /*CLEAN*/)) &&
       (cur_state != 3'd0) |-> (next_state == 3'd3 /*SC*/);
endproperty
 
// 3. SnpMakeInvalid NEVER returns data — its whole point is a no-data invalidation.
property p_makeinvalid_no_data;
  @(*) (snp_type == 3'd4 /*MAKEINVALID*/) |-> !send_data;
endproperty

The system point, beyond the checks:

The two axes are independent for a reason: state and data answer different coherence questions. The state axis answers "who may hold the line after this" — the sharing and exclusivity structure. The data axis answers "where does the latest value go" — preserved by forwarding, by writeback, or, when genuinely unneeded, discarded. Keeping them separate is what lets CHI have a no-data invalidation (SnpMakeInvalid) distinct from a data-preserving invalidation (SnpUnique, SnpCleanInvalid): same forced state, opposite data rule. The whole catalogue is disciplined by never conflating the two — and the danger, correspondingly, is choosing the no-data variant when the data axis actually mattered.

  • What it proves: invalidating → I, downgrading → SC, MakeInvalid → no data.
  • What it does not prove: the home picked the right snoop for the request — that is the flow's decode (Module 8).
  • Bug signature: a no-data snoop on a dirty holder whose data the requester needed — data destroyed.

13. Testbench — the catalogue against a dirty and a clean holder

Drives each snoop type against a UD holder and an SC holder, checking the forced state and data rule.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
module tb_chi_snoop_decode;
  logic [2:0] snp_type, cur_state, next_state;
  logic send_data;
  int errors = 0;
  localparam SNP_SHARED=3'd0, SNP_CLEAN=3'd1, SNP_UNIQUE=3'd2,
             SNP_CLEANINVALID=3'd3, SNP_MAKEINVALID=3'd4, SNP_ONCE=3'd5;
  localparam INV=3'd0, UC=3'd1, UD=3'd2, SC=3'd3, SD=3'd4;
 
  chi_snoop_decode dut (.*);
 
  task automatic check(input logic [2:0] sn, cs, exp_ns, input logic exp_sd, input string name);
    snp_type = sn; cur_state = cs; #1;
    if (next_state !== exp_ns || send_data !== exp_sd) begin
      errors++; $display("FAIL %s: next=%0d data=%0b", name, next_state, send_data);
    end else $display("PASS %s: next=%0d data=%0b", name, next_state, send_data);
  endtask
 
  initial begin
    // Against a Unique Dirty holder.
    check(SNP_SHARED,      UD, SC,  1'b1, "SnpShared/UD      -> SC, data");
    check(SNP_UNIQUE,      UD, INV, 1'b1, "SnpUnique/UD      -> I, data");
    check(SNP_CLEANINVALID,UD, INV, 1'b1, "SnpCleanInvalid/UD-> I, data");
    check(SNP_MAKEINVALID, UD, INV, 1'b0, "SnpMakeInvalid/UD -> I, NO data");
    check(SNP_ONCE,        UD, UD,  1'b1, "SnpOnce/UD        -> unchanged, copy");
    // Against a Shared Clean holder.
    check(SNP_SHARED,      SC, SC,  1'b0, "SnpShared/SC      -> SC, no data");
    check(SNP_UNIQUE,      SC, INV, 1'b0, "SnpUnique/SC      -> I, no data");
 
    if (errors == 0) $display("ALL TESTS PASSED");
    else             $display("%0d FAILURE(S)", errors);
    $finish;
  end
endmodule

Expected output:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
PASS SnpShared/UD      -> SC, data: next=3 data=1
PASS SnpUnique/UD      -> I, data: next=0 data=1
PASS SnpCleanInvalid/UD-> I, data: next=0 data=1
PASS SnpMakeInvalid/UD -> I, NO data: next=0 data=0
PASS SnpOnce/UD        -> unchanged, copy: next=2 data=1
PASS SnpShared/SC      -> SC, no data: next=3 data=0
PASS SnpUnique/SC      -> I, no data: next=0 data=0
ALL TESTS PASSED

14. DebugLab — SnpMakeInvalid where the dirty data was needed

1

SnpMakeInvalid where the dirty data was needed

SNPMAKEINVALID ON A DIRTY HOLDER WHOSE DATA WAS NEEDED -> DATA LOST
Symptom

A read or partial write returns or writes stale/garbage data for a line that another cache had modified — but only when that other cache held the line dirty, and only when the operation did not overwrite the whole line.

Evidence

An invalidation dropped the only current copy:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
RN1 = UD (value = NEW),  memory = OLD
requester needs the data (read or partial write)
HN issues SnpMakeInvalid to RN1   <-- no-data invalidation
RN1: UD -> I, discards NEW (nothing forwarded, nothing written back)
memory still = OLD, NEW is gone
requester proceeds with OLD/garbage -> lost modification

The holder was invalidated correctly, but its dirty data — which was needed — vanished with it.

First Divergence

The home issued SnpMakeInvalid — the no-data invalidating snoop — to a dirty holder whose data the requester needed. From that point the dirty bytes had no path out: MakeInvalid neither forwards nor writes back.

Root Cause

The data axis was chosen wrong. SnpMakeInvalid and SnpUnique/SnpCleanInvalid force the same state (Invalid) but differ on data: MakeInvalid returns none, by design, for requesters that will overwrite the whole line and need no old data. Using it when the requester does need the data drops the holder's dirty bytes. Same forced state, opposite data rule — and the wrong rule here means the latest value is destroyed, not preserved.

Fix

Choose the invalidating snoop by the data need: SnpUnique to forward the dirty data to the requester (it needs it), or SnpCleanInvalid to write it back to memory. Reserve SnpMakeInvalid for a full-line overwrite, where no old data is needed. The forced state is the same; only a data-returning variant preserves the modification.

15. Common Mistakes

  • No-data snoop where data was needed. Assumption: any invalidation works. Bug: dirty data lost (the DebugLab). Prevention: SnpUnique/SnpCleanInvalid when data is needed.
  • Downgrading where you needed to invalidate. Assumption: SnpShared suffices for a write. Bug: stale sharer (Chapter 8.1). Prevention: SnpUnique for exclusivity.
  • Invalidating where you needed to downgrade. Assumption: clear everyone. Bug: sharing destroyed (Chapter 8.1). Prevention: SnpShared for a read.
  • Forgetting SnpOnce leaves state unchanged. Assumption: every snoop changes state. Bug: mis-modeled holder. Prevention: SnpOnce is a snapshot.
  • Confusing forward and writeback. Assumption: returned data always goes to memory. Bug: mis-routed data. Prevention: SnpUnique forwards, SnpCleanInvalid writes back.
  • Picking the snoop by hand. Assumption: any snoop is fine. Bug: mismatch with the request. Prevention: the request opcode dictates the snoop.

16. Engineering Checklist

  • Place each snoop on two axes — forced state and data requirement.
  • Use SnpShared / SnpClean to downgrade to SC; SnpUnique / SnpCleanInvalid / SnpMakeInvalid to invalidate.
  • Return dirty data with a data-returning snoop; use SnpMakeInvalid only for full overwrites.
  • Route returned data correctly — forward (SnpUnique) or writeback (SnpCleanInvalid / SnpClean).
  • Use SnpOnce for a snapshot that leaves the holder unchanged.
  • Let the request opcode select the snoop; verify the pairing.

17. Key Takeaways

  • Every snoop is a forced state (SC / I / unchanged) paired with a data rule — two axes.
  • Downgrading: SnpShared, SnpClean → SC. Invalidating: SnpUnique, SnpCleanInvalid, SnpMakeInvalid → I.
  • On data: most return the line if dirty; SnpMakeInvalid never; SnpOnce always (a snapshot).
  • Returned dirty data is forwarded (SnpUnique) or written back (SnpCleanInvalid / SnpClean).
  • The request opcode chooses the snoop; a no-data invalidation on needed dirty data destroys it.
  • Reason on the two axes, match the snoop to the intent; the model here is representative.

18. Quick Revision

Snoop request types. Every snoop opcode is defined by two axes: the state it forces in the holder, and its data rule. On state: SnpShared and SnpClean downgrade to SC (holder keeps a readable copy); SnpUnique, SnpCleanInvalid, and SnpMakeInvalid invalidate to I; SnpOnce leaves the state unchanged (a snapshot); SnpNotSharedDirty lets the holder keep SD. On data: most return the line only if dirty, SnpMakeInvalid returns none, and SnpOnce always takes a copy. Where dirty data comes back it is either forwarded to the requester (SnpUnique) or written back to memory (SnpCleanInvalid, SnpClean). The request opcode selects the snoop to match its intent — ReadShared → SnpShared, ReadUnique → SnpUnique, MakeUnique → SnpMakeInvalid. The sharp edge is the data axis: SnpMakeInvalid and SnpUnique force the same state but the former returns no data, so issuing it to a dirty holder whose data was needed destroys the modification. Reason on the axes; match the snoop to the request. Representative model; 9.3 covers the snoop responses.

Coming Next

Chapter 9.3 — Snoop Responses. This chapter catalogued the snoops the home sends; the next catalogues what comes back. Chapter 9.3 covers the snoop response packets — SnpResp and its variants, with and without data — and what each implies about the snooped cache's new state and the data it holds. It is the return half of the exchange: how a holder tells the home what it did, and how the home reads that response to complete the transaction that issued the snoop.