Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • How to Use This Course
  • Reading Path
  • Cache Coherency Glossary
  • The Shared Course Model
  • Cache Coherency Revision Sheet
  • Why Coherence Exists8
  • States and Protocols12
  • Transactions12
  • Races and Controller Design8
  • Progress and the Fabric16
  • Ordering and Synchronization12
  • Performance and Scalability12
    • False Sharing
    • Directory Capacity and Sharers
      • Full Bit-Vector Cost
      • Limited Pointers and Coarse Vectors
      • Sparse Directories and Eviction
      • Conservative Metadata Rules
    • Hotspots and Placement
  • Real Protocols12
  • SoC Integration12
  • Power, Clocking and Reliability12
  • Verification12
  • Debug and Bring-up12
  • Interview and Design Review17
  • Capstone: A Coherent Model Lab5
Loading lesson

‹Directory Capacity and Sharers
  1. Topics
  2. Cache Coherency
  3. Performance and Scalability
  4. Directory Capacity and Sharers
  5. Conservative Metadata Rules

Part 7 · Performance and Scalability · All levels

Conservative Metadata Rules

Turn coverage through overflow and eviction into explicit review rules and a randomised check of a Dir_i B entry.

On this page

    What must remain true while H's entry changes?

    Rule: whenever H chooses which caches to send Inv or Fwd to for X, every cache that may hold X must be among them. That includes a cache whose fill H has admitted but not yet delivered, and the cache holding the dirty copy. A change of representation (pointers to overflow, pointers to group bits, entry eviction) must keep this true at every step of the change, not only before and after it.

    This is the inclusive-filter invariant of Snoop Filter Correctness, applied here to pointer overflow and its two classic bugs.

    Checking a Dir_i B entry

    The program models one K-pointer Dir_i B entry, as in Limited Pointers and Coarse Vectors, over random GetS, Put and GetM events with a fixed seed. After every event it asserts that the caches really holding X are a subset of the candidates the entry implies: the pointers, or all caches when overflow is set. Two injected bugs must each break that: truncating to K ids without setting overflow, and clearing overflow on a PutS. It also replays the four-core case and checks that C3's GetM invalidates C0, C1 and C2, with C2's ack the wasted one.

    example.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    # Simplified: one entry, each event completes atomically (no transients or
    # in-flight fills), H updates the entry at once, Inv-Acks are not modelled.
    import random
    def candidates(e, n):
        if e["state"] == "U":
            return set()
        if e["state"] == "S" and e["ovf"]:
            return set(range(n))  # Dir_i B: overflow means every cache may hold X
        return set(e["ptr"])
    def add_sharer(e, c, k, bug):
        if c in e["ptr"] or e["ovf"]:
            return
        if len(e["ptr"]) < k:
            e["ptr"].add(c)
        elif bug != "truncate":
            e["ovf"] = True  # keep the K pointers, mark the set incomplete
    def step(e, holders, op, c, n, k, bug):
        if op == "GetS" and c not in holders:
            if e["state"] == "U":
                e.update(state="exclusive", ptr={c}, ovf=False)  # MESI: sole reader gets E
            else:
                e["state"] = "S"  # a previous exclusive holder is downgraded to S
                add_sharer(e, c, k, bug)
            holders.add(c)
        elif op == "GetM":
            inv = candidates(e, n) - {c}
            wasted = inv - holders  # Inv-Acks sent from I
            holders -= inv
            holders.add(c)
            e.update(state="exclusive", ptr={c}, ovf=False)  # cleared only here
            return inv, wasted
        elif op == "Put" and c in holders:  # PutS, or PutE/PutM from the exclusive holder
            holders.discard(c)
            if e["state"] == "exclusive":
                e.update(state="U", ptr=set(), ovf=False)
            elif e["ovf"] and bug == "clear_on_puts":
                e["ovf"] = False
                e["ptr"].discard(c)
            elif not e["ovf"]:
                e["ptr"].discard(c)
                if not e["ptr"]:
                    e.update(state="U")
        return None
    def run(n, k, bug=None, seed=7, steps=3000):
        rng = random.Random(seed)
        e, holders = {"state": "U", "ptr": set(), "ovf": False}, set()
        for _ in range(steps):
            step(e, holders, rng.choice(["GetS", "GetS", "Put", "GetM"]), rng.randrange(n), n, k, bug)
            if not holders <= candidates(e, n):
                return False
        return True
    for n in (4, 8):
        for k in (1, 2):
            assert run(n, k)
            assert not run(n, k, bug="truncate")
            assert not run(n, k, bug="clear_on_puts")
    # The lesson's 4-core, K = 1 case: C0 and C1 read, then C3 writes.
    e, holders = {"state": "U", "ptr": set(), "ovf": False}, set()
    for op, c in (("GetS", 0), ("GetS", 1)):
        step(e, holders, op, c, 4, 1, None)
    assert e["ptr"] == {0} and e["ovf"]
    inv, wasted = step(e, holders, "GetM", 3, 4, 1, None)
    assert inv == {0, 1, 2} and wasted == {2} and holders == {3}
    print("PASS: Dir_i B covers every holder, truncation and PutS clearing both fail")

    Transition under review

    Required evidence

    Grant a new fill

    The reader is in H's entry (pointer, overflow or group bit) before Data leaves H.

    Enter pointer overflow

    The overflow bit is set before the read that did not fit is granted.

    Clear overflow

    Only after a GetM's Inv to every other cache has collected every Inv-Ack.

    Clear a group bit

    No cache in that group may still hold X or have an admitted fill.

    Reuse an evicted entry

    Every listed sharer has acked its Inv, or the exclusive holder's Data has reached memory.

    Accept the dirty copy

    The Data reaches memory or the new holder before H's entry for the old holder is dropped.

    The new entry or fallback bit is in place and pending fills and Puts are accounted for before the old representation is dropped.
    A safe transition covers every cache that may hold X at every step, with no gap between representations.

    The program checks only candidate coverage. It does not check response matching, data movement or eventual service; those remain with ack and data tracking and the controller resources. A pointer format with good storage arithmetic can still have a broken transition.

    Common pitfall

    Verifying only stable full and overflow states while allowing a step in which neither representation covers the new reader.

    Interview

    Ask what covers an in-flight fill during an eviction or overflow. A complete answer names the pointer, bit or pending entry, not just a final bitmap.

    Check yourself Does a conservative candidate set prove the newest value is delivered?

    No. It proves every cache that may hold X is reached. The Data must still come from the cache holding the dirty copy, or from memory when it is current, and must match the request it answers.

    Related topics

    • Shared course model

    • Overflow schemes

    Previous

    81 / 167

    Next: Hotspots and Placement

    Up next

    Up nextHotspots and Placement

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Full Bit-Vector Cost
    • Limited Pointers and Coarse Vectors