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
    • Transient States and Races
    • Controller Resources
      • MSHRs and Pending Entries
      • Ack Counting and Late Data
      • Retries, NACKs and Credits
      • A Controller Block Diagram
  • Progress and the Fabric16
  • Ordering and Synchronization12
  • Performance and Scalability12
  • Real Protocols12
  • SoC Integration12
  • Power, Clocking and Reliability12
  • Verification12
  • Debug and Bring-up12
  • Interview and Design Review17
  • Capstone: A Coherent Model Lab5
Loading lesson

‹Controller Resources
  1. Topics
  2. Cache Coherency
  3. Races and Controller Design
  4. Controller Resources
  5. Ack Counting and Late Data

Part 4 · Races and Controller Design · All levels

Ack Counting and Late Data

Complete revocations and authoritative-data collection independently before issuing writable Data.

On this page

    What if the last ack arrives before the bytes?

    A zero acknowledgement count means the specified revocations are complete. It does not make missing data appear. The converse is equally important: receiving the current value does not prove another cache has lost permission. This example keeps both dependencies at H, so the final Data still combines a usable value with the M grant.

    Warm-up from X = 0: a previous write of 1 was completed and cleaned to memory, and C0 then obtained S / 1. Now C0 S / 1, C1 I / -, H S{C0}, memory = 1, MSI. C1 requests GetM A. H starts a memory read and sends an invalidation, then receives Inv-Ack before the memory read returns. Only A is active; a conflicting request would wait. Memory is authoritative because the old holder is clean S, not a dirty exclusive cache.

    H receives C0's invalidation acknowledgement before the memory read returns, and grants C1 M only after both have arrived.
    Acks-first completion: H waits for authoritative data even after C0's revocation is confirmed.

    Step

    C0 state / value

    C1 state / value

    H directory

    Memory

    Newest data

    Initial

    S / 1

    I / -

    S{C0}

    1

    C0 and memory: 1

    1. GetM A at H

    S / 1

    IM^D / -

    S{C0}, pend GetM C1, acks 0/1, data pending

    1

    C0 and memory: 1

    2. Inv at C0

    I / -

    IM^D / -

    S{C0}, pend GetM C1, acks 0/1, data pending

    1

    memory: 1

    3. Inv-Ack at H

    I / -

    IM^D / -

    U, pend GetM C1, acks 1/1, data pending

    1

    memory: 1

    H reads memory

    I / -

    IM^D / -

    U, pend GetM C1, acks 1/1, data valid

    1

    H buffer and memory: 1, Data(1) in flight to C1

    4. Data at C1

    I / -

    M / 1

    U, pend GetM C1, acks 1/1, data valid

    1

    C1 and memory: 1

    (assumed) grant delivered

    I / -

    M / 1

    exclusive(C1)

    1

    C1 and memory: 1

    L. Local store

    I / -

    M / 2

    exclusive(C1)

    1

    C1: 2

    Authoritative data ready?

    Required ack set empty?

    Issue grant?

    No

    No

    No: two obligations remain.

    No

    Yes

    No: do not invent a payload.

    Yes

    No

    No: readers may still be usable.

    Yes

    Yes

    Eligible if identity, state and protected output capacity are also correct.

    Not the course's convention: in the Primer's directory protocol, invalidated caches send Inv-Acks straight to the requester, and Data carries the number of acks to expect. The requester waits in IM^AD or SM^AD. Because there is no FIFO order, an Inv-Ack can arrive before the Data that says how many to expect, so the requester keeps a signed counter: each early Inv-Ack decrements it below zero, and the ack count in Data adds back. The requester completes when Data has arrived and the counter is zero.

    Count identities, not just packets

    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
    def receive(entry, transaction, kind, responder=None, value=None):
        if transaction != entry["id"]:
            return False
        if kind == "ack":
            if responder not in entry["waiting"]:
                return False
            entry["waiting"].remove(responder)
        elif kind == "data":
            if value is None or entry["data"] is not None:
                return False
            entry["data"] = value
        else:
            return False
        return True
    def ready(entry):
        return not entry["waiting"] and entry["data"] is not None
    for order in [("ack", "data"), ("data", "ack")]:
        entry = {"id": "A", "waiting": {"C0"}, "data": None}
        assert not ready(entry)
        assert not receive(entry, "old", "ack", responder="C0")
        assert not receive(entry, "old", "data", value=99)
        for position, kind in enumerate(order):
            assert receive(entry, "A", kind, responder="C0", value=0)
            assert ready(entry) == (position == 1)
        assert not receive(entry, "A", "ack", responder="C0")
        assert not receive(entry, "A", "data", value=99)
        assert entry["data"] == 0 and ready(entry)
    print("PASS: both arrival orders require matching acks and present data")

    Simulation: two acks, data in between

    The waveform below is simulation output for H's pending entry in a three-core variant of the model: C0 and C2 hold X in S, memory is authoritative, and C1 sends GetM. H collects two Inv-Acks and the memory data. Here the data arrives between the two acks, whereas in the table above the ack came first. One slot is one clock cycle.

    How to read it: C1's GetM is accepted in slot 1. In slot 2 the entry is pending, inv_sent pulses (Inv to C0 and C2) and acks_left is 2. C0's Inv-Ack in slot 4 brings acks_left to 1 in slot 5. The memory read returns in slot 6, so data_valid is high in slots 7 and 8, but grant stays low: one ack is still missing. C2's Inv-Ack in slot 8 brings acks_left to 0 in slot 9, and grant (Data with M permission to C1) pulses in that same slot while pending and data_valid clear. store_done rises in slot 10: C1's store completes only after the grant.

    The code checks both arrival orders and rejects stale identities and duplicate responses without changing the accepted value. A counter can replace the expected-responder set only if each required response is counted exactly once.

    Common pitfall

    Using data's truth value as its presence flag rejects a valid zero payload. Similarly, blindly decrementing a counter on duplicate Inv-Ack can turn an outstanding reader into a false completion.

    Interview

    Explain both arrival orders. H may buffer data while waiting for revocations, or wait for data after acks complete. Neither event alone completes the grant.

    Check yourself At step 3 memory contains 1. Why not immediately grant C1 M with Data(1)?

    H has not yet read it. The 1 in the table stands for the whole 64-byte line, which H must read from memory and hold in its buffer before it can send it. Knowing the value in a worked example is not the same as having the data.

    Related topics

    • Shared course model

    • Compare: permission-only upgrade

    Previous

    43 / 167

    Next: Retries, NACKs and Credits

    Up next

    Up nextRetries, NACKs and Credits

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • A Controller Block Diagram
    clkgetmpendinginv_sentacks_left0210inv_ackdata_validgrantstore_done
    Simulation output: H's pending entry for a GetM with two sharers, granting only when the ack count reaches zero with data present