Skip to content

AMBA CHI · Module 10 · Cache State Management

Ownership in CHI

Module 9 moved ownership between caches; this chapter asks the standing question — at any moment, who owns the line? Ownership is the responsibility for a line's latest value and its writeback: exactly one owner at all times. A clean line is owned by memory; a dirty line by exactly one Request Node, in UniqueDirty or SharedDirty. The subtlety is that ownership is tracked in two places: the owning cache knows from its state, and the home's directory separately records the owner. The two must agree, since the home routes by the directory. Let them drift and the home chases dirty data at the wrong node, losing the modification or serving stale memory. Representative model, not the specification.

Intermediate15 min readAMBA CHIOwnershipDirectoryCoherencyWriteback

Module 10 · Chapter 10.3 · Cache State Management

Project thread — 10.2 gave the transitions. This chapter tracks ownership through them: who owns the line at each moment. 10.4 turns to sharing.

1. Learning Outcomes

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

  • Define ownership as the responsibility for a line's latest value and its writeback.
  • State the invariant: exactly one owner at all times — memory or a single RN.
  • Identify the owner from a line's state — UD/SD owns; UC/SC/I does not.
  • Explain why ownership is dual-tracked — the cache state and the home's directory.
  • Diagnose what breaks when the two records disagree.
  • Implement a representative owner resolver in SystemVerilog, Verilog-2001, and VHDL.

2. Why Should I Learn This?

Ownership is the question the home must answer before almost any transaction: who has the current data, and who owes the writeback? Every snoop routes to the owner; every writeback comes from the owner; every read of a dirty line is satisfied by the owner. If the home cannot name the owner correctly at any given moment, it cannot coordinate coherence at all.

CHI makes the answer crisp — exactly one owner, always — but the crispness rests on agreement between two separate records. The owning cache knows it owns the line because its state says so; the home knows because its directory says so. These are two copies of one fact, and coherence depends on them matching. This chapter is about keeping that fact single and consistent — the discipline that lets the home always point to the right node.

3. Key Terms

4. Previous Chapter Connection

Chapter 9.6 moved ownership between caches and showed it must be conserved at exactly one. Chapter 10.1 introduced SD as the shared-dirty owner, and 10.2 moved lines through the states. This chapter asks the standing question underneath all of it: at any moment, who owns this line?

The answer is read from the states you already know: a cache in UD or SD owns the line; UC, SC, I do not; and if no cache owns it, memory does. But ownership is also recorded independently at the home, in its directory, so it can act without inspecting caches. This chapter ties the state view and the directory view together — the two must always name the same owner — turning the transfers of Module 9 into a property the home can query at every step.

5. Core Concept — one owner, tracked in two places

At every moment a line has exactly one owner, and that fact is recorded in two places that must agree.

  • One owner, always. A clean line is owned by memory — no cache owes a writeback. A dirty line is owned by exactly one RN, the cache in UD (sole) or SD (shared owner). Never zero, never two.
  • The cache knows from its state. A cache in UD/SD knows it is the owner — it holds the latest data and owes the writeback. A cache in UC/SC/I knows it is not the owner.
  • The home knows from its directory. The home records who the owner is, so it can route a snoop to the owner and expect a writeback from it — without inspecting the caches.
  • The two must agree. The cache's owning state and the directory's owner record are two copies of one fact. If they disagree — a cache no longer owns but the directory still names it — the home acts on a falsehood.

The synthesis:

A line has exactly one owner at all times: memory if clean, one RN (UD/SD) if dirty. Ownership is dual-tracked — the owning cache knows from its state, and the home knows from its directory — and the two records must agree. The home relies on the directory to route snoops and collect writebacks, so a disagreement sends it to the wrong node.

6. Engineering Mental Model — the on-call board and the pager

Return to the on-call pager (Chapter 9.6), now with a board on the wall.

  • Exactly one person carries the pager — the owner of incidents. If no one is actively on call, the front desk (memory) handles them by default.
  • The person carrying the pager knows they are on call — that is their state. Separately, the wall board lists who is on call — that is the directory.
  • The team reads the board to know who to escalate to; they do not go person-to-person asking "do you have the pager?"
  • So the board and the pager-holder must match. If the pager is handed off but the board is not updated, the team escalates to the person named on the board — who no longer has the pager — and the incident goes to someone who cannot handle it.

The board is a convenience — it lets everyone find the owner fast — but only while it tells the truth. Keep the board in step with who actually holds the pager.

7. Engineering Diagram — who owns the line

Ownership at a moment. The Home Node directory records the owner as RN1. RN1 holds the line in Unique Dirty and is the owner. RN2 holds a shared copy and is not the owner. Memory owns clean lines when no cache owns the line. The directory's owner record and RN1's state must agree.HN Directoryowner = RN1RN1 · UDthe ownerRN2 · SCsharer, not ownerMemoryowns clean linesowns12
Figure 1 — ownership at a moment. The Home Node's directory records the current owner and points to it: here RN1, which holds the line in UniqueDirty. RN2 holds a plain shared copy and is not the owner. Memory owns clean lines when no cache does. The owner is recorded both in RN1's state (UD) and in the directory (owner = RN1); the two must name the same node.

The directory points to RN1 as the owner, and RN1's state (UD) agrees. RN2 is a sharer, not an owner; memory owns clean lines when no cache does. Two records, one owner — and they name the same node.

8. Who Owns the Line, by State

Read ownership straight from the line's state.

StateOwns the line?Who owes writeback
Inomemory (no cache holds it)
UCnomemory (clean)
SCnothe SD owner, or memory
UDyesthis cache
SDyesthis cache
(no cache dirty)memory

The rule to carry: the dirty states — UD and SD — are the owning states; a cache in either owns the line and owes the writeback. Every other state does not own it. And if no cache is dirty, memory owns the line. So ownership is fully determined by "is any cache dirty, and which one" — one owner, always identifiable.

9. Dual-Tracked Ownership — cache state and directory

Ownership lives in two records, and their relationship is the crux.

  • The cache state is the ground truth for one line. A cache in UD/SD is the owner; its state cannot lie about its own responsibility.
  • The directory is the home's index. It records the owner across all caches, so the home can find the owner of any line without polling every cache.
  • The directory is a cache of the truth. Like any index, it is only useful while it matches reality — the owning cache's state.
  • Every ownership change updates both. A transfer (Chapter 9.6), a writeback, or an upgrade changes who owns the line — and must update the directory as well as the cache states, or the two drift apart.

The point to carry:

The directory exists so the home can answer "who owns this line?" instantly, without inspecting caches — but that answer is only correct while the directory agrees with the caches' states. Ownership is one fact stored twice: once where it is enforced (the owning cache's state) and once where it is queried (the directory). Every event that changes the owner must update both copies together. Update only one and the home's index points at a node whose state has moved on — and the home will act on the stale index, not the reality.

10. Reading Ownership — through a transfer

Follow the owner as a line moves; watch both records.

  1. Start. RN1 holds the line UD (owner). Directory: owner = RN1. Both agree.
  2. RN0 ReadUnique. The home snoops the owner it has recorded — RN1 — with SnpUnique.
  3. Transfer. RN1 relinquishes (UD → I, PassDirty); RN0 assumes (installs UD). The owner is now RN0.
  4. Update both. RN1's state is now I (not owner); RN0's is UD (owner); the directory updates to owner = RN0. Both records agree again.
  5. Next. A later snoop routes to RN0 — the correct, current owner — because the directory tracked the change.

Ownership stayed single and knowable throughout: the state said it, the directory recorded it, and step 4 kept them in step. Skip the directory update in step 4 and the home would still snoop RN1 — the DebugLab.

11. RTL / Hardware View — an owner resolver

The home's owner logic is small: if any cache holds the line dirty, that cache is the owner; otherwise memory owns it. A consistency check compares the cache's self-view with the directory's record. Representative.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Representative ownership resolver (educational).
// Exactly one owner: if a cache holds the line dirty, it owns; else memory owns.
// The directory's recorded owner must agree with the owning cache's state.
module chi_owner_resolve #(parameter IDW = 3) (
  input  logic           dirty_holder_valid, // some cache holds the line dirty
  input  logic [IDW-1:0] dirty_holder_id,    // which cache (from directory)
  input  logic           rn_thinks_owner,    // that cache's state says it owns (UD/SD)
  input  logic [IDW-1:0] dir_owner_id,        // the directory's recorded owner
  output logic           owner_is_cache,     // a cache owns the line
  output logic           owner_is_memory,    // memory owns the line (clean)
  output logic [IDW-1:0] owner_id,           // the owning cache (valid if owner_is_cache)
  output logic           consistent          // cache state and directory agree
);
  assign owner_is_cache  = dirty_holder_valid;
  assign owner_is_memory = !dirty_holder_valid;
  assign owner_id        = dirty_holder_id;
  // Consistency: if a cache owns, its self-view and the directory's owner must match.
  assign consistent = owner_is_memory ||
                      (rn_thinks_owner && (dir_owner_id == dirty_holder_id));
endmodule

The same behavior in Verilog-2001:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Representative ownership resolver (Verilog-2001).
module chi_owner_resolve #(parameter IDW = 3) (
  input            dirty_holder_valid,
  input  [IDW-1:0] dirty_holder_id,
  input            rn_thinks_owner,
  input  [IDW-1:0] dir_owner_id,
  output           owner_is_cache,
  output           owner_is_memory,
  output [IDW-1:0] owner_id,
  output           consistent
);
  assign owner_is_cache  = dirty_holder_valid;
  assign owner_is_memory = !dirty_holder_valid;
  assign owner_id        = dirty_holder_id;
  assign consistent = owner_is_memory ||
                      (rn_thinks_owner && (dir_owner_id == dirty_holder_id));
endmodule

And in VHDL:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-- Representative ownership resolver (VHDL).
library ieee;
use ieee.std_logic_1164.all;
 
entity chi_owner_resolve is
  generic ( IDW : integer := 3 );
  port (
    dirty_holder_valid : in  std_logic;
    dirty_holder_id    : in  std_logic_vector(IDW-1 downto 0);
    rn_thinks_owner    : in  std_logic;
    dir_owner_id       : in  std_logic_vector(IDW-1 downto 0);
    owner_is_cache     : out std_logic;
    owner_is_memory    : out std_logic;
    owner_id           : out std_logic_vector(IDW-1 downto 0);
    consistent         : out std_logic
  );
end entity;
 
architecture rtl of chi_owner_resolve is
begin
  owner_is_cache  <= dirty_holder_valid;
  owner_is_memory <= not dirty_holder_valid;
  owner_id        <= dirty_holder_id;
  consistent <= '1' when (dirty_holder_valid = '0') or
                         (rn_thinks_owner = '1' and dir_owner_id = dirty_holder_id)
                else '0';
end architecture;

All three name a single owner — a dirty cache or memory — and flag consistent only when the directory's record agrees with the owning cache's state. The DebugLab shows the failure when they disagree.

12. Verification View — one owner, records agree

The properties that keep ownership sound: exactly one owner, and the two records agree.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Bind to chi_owner_resolve.
// 1. Exactly one owner — a cache xor memory.
property p_one_owner;
  @(*) owner_is_cache ^ owner_is_memory;
endproperty
 
// 2. When a cache owns, the directory's owner must match that cache's self-view.
property p_records_agree;
  @(*) owner_is_cache |-> (consistent == (rn_thinks_owner && (dir_owner_id == owner_id)));
endproperty
 
// 3. A clean line (no dirty holder) is owned by memory.
property p_clean_owned_by_memory;
  @(*) (!dirty_holder_valid) |-> owner_is_memory;
endproperty

The system point, beyond the checks:

Ownership is where a coherence protocol's distributed truth is made queryable. The fact "who owns this line" is enforced in a cache far from the home, but the home must know it to act — so it keeps a local index, the directory. The whole scheme works only because the index is maintained as a faithful mirror: every event that changes the owner updates both the enforcing state and the querying index in lockstep. A directory that can drift from the caches is not a performance shortcut but a correctness hazard, because the home does not double-check the caches — it trusts the index. Ownership is single and knowable precisely as long as its two records are kept identical.

  • What it proves: exactly one owner; the records agree when a cache owns; memory owns clean lines.
  • What it does not prove: the directory is actually updated on every event — that is the controller's duty.
  • Bug signature: consistent low — the directory names an owner whose state has moved on.

13. Testbench — ownership and consistency

Drives clean and dirty ownership, and an agreeing and disagreeing directory record.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
module tb_chi_owner_resolve;
  localparam IDW = 3;
  logic dirty_holder_valid, rn_thinks_owner, owner_is_cache, owner_is_memory, consistent;
  logic [IDW-1:0] dirty_holder_id, dir_owner_id, owner_id;
  int errors = 0;
 
  chi_owner_resolve #(.IDW(IDW)) dut (.*);
 
  task automatic check(input logic dv, rt, input logic [IDW-1:0] dhid, doid,
                       input logic exp_cache, exp_cons, input string name);
    dirty_holder_valid = dv; dirty_holder_id = dhid;
    rn_thinks_owner = rt; dir_owner_id = doid; #1;
    if (owner_is_cache !== exp_cache || consistent !== exp_cons) begin
      errors++; $display("FAIL %s: cache=%0b cons=%0b", name, owner_is_cache, consistent);
    end else $display("PASS %s: cache=%0b cons=%0b", name, owner_is_cache, consistent);
  endtask
 
  initial begin
    check(1'b0, 1'b0, 3'd0, 3'd0, 1'b0, 1'b1, "clean -> memory owns, consistent");
    check(1'b1, 1'b1, 3'd2, 3'd2, 1'b1, 1'b1, "dirty RN2, dir=RN2 -> owner RN2, consistent");
    check(1'b1, 1'b1, 3'd2, 3'd5, 1'b1, 1'b0, "dirty RN2, dir=RN5 -> DISAGREE");
    check(1'b1, 1'b0, 3'd2, 3'd2, 1'b1, 1'b0, "dir=RN2 but RN2 not owning -> DISAGREE");
 
    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 clean -> memory owns, consistent: cache=0 cons=1
PASS dirty RN2, dir=RN2 -> owner RN2, consistent: cache=1 cons=1
PASS dirty RN2, dir=RN5 -> DISAGREE: cache=1 cons=0
PASS dir=RN2 but RN2 not owning -> DISAGREE: cache=1 cons=0
ALL TESTS PASSED

14. DebugLab — the directory and the cache disagree on the owner

1

The directory and the cache disagree on the owner

DIRECTORY OWNER DISAGREES WITH CACHE STATE -> DIRTY LOST / STALE READ
Symptom

The home occasionally snoops a node that does not have the line, and a modification is lost or a read returns stale data — but only after ownership has moved between caches. Ownership that stays put is always correct.

Evidence

The directory named an ex-owner:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
before: RN1 = UD (owner),  directory owner = RN1   (agree)
ownership transfers to RN0: RN1 -> I, RN0 -> UD
  directory NOT updated -> still owner = RN1   <-- drift
later: home needs the dirty data -> snoops RN1 (per directory)
  RN1 has nothing (it is I) -> home gets no data
  home falls back to memory (stale) or drops the transaction

The real owner was RN0, but the directory still pointed at RN1.

First Divergence

Ownership moved from RN1 to RN0, updating the cache states, but the directory owner record was not updated. From that point the home's index disagreed with the caches, and the home trusted the index.

Root Cause

Ownership is one fact stored twice, and both copies must change together. The cache states enforce ownership; the directory indexes it so the home can act without polling. When the states change owner but the directory does not, the home routes to the node the directory names — the ex-owner — and misses the real owner's data. This is a consistency failure between the two records, distinct from mis-conserving ownership across a transfer (Chapter 9.6): the transfer was correct at the caches, but the directory was left stale.

Fix

Update the directory owner record on every ownership change — transfer, writeback, upgrade — in lockstep with the cache-state change, so consistent always holds. The home's index then names the node whose state actually owns the line, and snoops and writebacks route to the real owner.

15. Common Mistakes

  • Directory drift. Assumption: updating the cache state is enough. Bug: home snoops an ex-owner (the DebugLab). Prevention: update both records together.
  • Assuming memory owns a dirty line. Assumption: memory is always current. Bug: stale read (Chapter 9.5). Prevention: a dirty cache owns, not memory.
  • Two owners. Assumption: dirty data can be co-owned. Bug: double writeback. Prevention: exactly one owner (Chapter 9.6).
  • Zero owners. Assumption: relinquish without handoff. Bug: lost data. Prevention: memory or one RN always owns.
  • Reading ownership from the wrong axis. Assumption: shared means not-owner. Bug: SD is a shared owner. Prevention: dirty states own, regardless of shared/unique.
  • Polling caches instead of the directory. Assumption: ask every cache. Bug: slow, unscalable. Prevention: trust a consistent directory.

16. Engineering Checklist

  • Ensure exactly one owner at all times — memory or a single RN.
  • Read ownership from the state — UD/SD owns; UC/SC/I does not.
  • Record the owner in the directory so the home can route snoops.
  • Update both records — cache state and directory — on every ownership change.
  • Verify consistency — the directory names the node whose state owns the line.
  • Route snoops and writebacks to the directory owner, kept current.

17. Key Takeaways

  • A line has exactly one owner at all times: memory (clean) or a single RN in UD/SD (dirty).
  • Ownership is read from the state — UD and SD own; UC, SC, I do not.
  • It is dual-tracked: the owning cache knows from its state; the home knows from its directory.
  • The two records must agree — the home routes snoops and writebacks by the directory.
  • If they disagree — an ex-owner still named by the directory — the home chases dirty data at the wrong node.
  • Keep one owner, tracked in two records kept consistent; the model here is representative.

18. Quick Revision

Ownership in CHI. At every moment a line has exactly one ownermemory if the line is clean, a single Request Node if it is dirty, in UD (sole) or SD (shared owner). Ownership is read straight from the state: UD/SD own; UC, SC, I do not. It is dual-tracked: the owning cache knows it owns the line from its state, and the home separately records the owner in its directory so it can route snoops and collect writebacks without polling caches. The two records are one fact stored twice, and they must agree — every ownership change (transfer, writeback, upgrade) must update both in lockstep. If they drift — a cache relinquishes ownership but the directory still names it — the home snoops the ex-owner, which no longer has the dirty data, and the modification is lost or memory is read stale. One owner, always; recorded in the state and the directory; kept consistent. Representative model; 10.4 turns to sharing — multiple readers and forwarding decisions.

Coming Next

Chapter 10.4 — Sharing in CHI. Ownership tracked the single owner; sharing tracks the many readers. Chapter 10.4 covers the Shared states — how multiple caches hold the same line read-only at once, how the home tracks the sharer set, and the forwarding decisions it makes when a new reader wants a copy that several caches already hold. It is the multi-reader counterpart to this chapter's single-owner view.