In the flat course model H names cores. This lesson groups cores into clusters. A cluster is a set of cores behind one local proxy: a controller that tracks its own cores and talks to the global home on their behalf. K0 = {C0, C2} with proxy H0, and K1 = {C1} with proxy H1. C2 is a third core, added because a local-sharing example needs two cores in one cluster; the course model allows this expansion when sharing needs it. The original H is the global home for X.
A local record (at H0 or H1) names cores in its cluster. The global record, labelled G, lives at H and names clusters. exclusive(K0) means K0 holds the only global permission for X. It does not mean H0 itself holds an M copy.
Start with X = 0 uncached. The rows are independent settled snapshots, not a sequence. Directory cells read G | H0 | H1, with clusters named at G and cores named at H0 and H1.
Snapshot | C0 state/value | C2 state/value | C1 state/value | Directory (G | H0 | H1) | memory value | Newest data |
|---|---|---|---|---|---|---|
Initial | I / - | I / - | I / - | G: U | H0: U | H1: U | 0 | memory: 0 |
C0 and C1 read X = 0 | S / 0 | I / - | S / 0 | G: S{K0,K1} | H0: S{C0} | H1: S{C1} | 0 | C0, C1 and memory: 0 |
C0 has M and stored 1 | M / 1 | I / - | I / - | G: exclusive(K0) | H0: exclusive(C0) | H1: U | 0 | C0: 1 |
C0 and C2 share the dirty value inside K0 | S / 1 | S / 1 | I / - | G: exclusive(K0) | H0: S{C0,C2}, dirty at H0 | H1: U | 0 | H0, C0 and C2: 1 |
H0 can grant its cores only what H granted K0. The global record for K0 limits the local states, and decides which local requests must go to H.
Global record for K0 | Allowed local states | Local action that needs H |
|---|---|---|
U | All I | Any fill (GetS or GetM from C0 or C2) |
S{K0, ...} | S only | Any GetM |
exclusive(K0) | One M, or several S with the dirty data held at H0 | None for X |
The last snapshot row shows the third case. K0 holds global write permission, so when C2 asked to read, H0 recalled the dirty value from C0, kept it, and gave S copies to both cores without contacting H. H0 is now K0's dirty-responsible holder, and G is unchanged because no message reached H. If C2 later asks to write, H0 invalidates C0 inside K0, again without H. Real two-level designs use the same idea: an inclusive shared L2 (one that holds every line its L1s hold) can hold M globally while its L1s share read-only copies.
Coverage means a record that leads a request to every cache that may hold a copy. If a core can hold a copy or has an admitted fill, the global level must keep coverage of its cluster, and the local level must cover the core. A local filter eviction cannot erase the last path by which a global request will find C0's M / 1. Records may over-cover; under-covering a cluster can lose a permission or the newest data.
This is an inclusive coverage policy. It does not require an inclusive shared data cache, and it is not the only hierarchical design. With K0 = {C0, C2} and K1 = {C1} the hierarchy saves no metadata (Hierarchy Trade-Offs counts it); it shows the scopes. Larger clusters let the global level summarize many cores, at the cost of local tracking and extra coordination.
For a concrete implementation to compare, gem5 MESI_Two_Level documents private L1 caches, a shared L2 with co-located directory information, and L1/L2 inclusion. That is one specific organisation, not the specification of our H0/H1 proxy extension.
No. The global home would lose its route to the newest value and to a conflicting permission. H0 must first resolve that responsibility, for example by writing the line back through H.