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
    • Read and Write-Permission Flows
    • Forwarding Versus Memory Sourcing
      • Who May Supply Data?
      • Dirty Intervention
      • Three-Hop Versus Four-Hop
      • When Memory Is Stale
    • Writeback, Eviction and Cleaning
  • Races and Controller Design8
  • 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

‹Forwarding Versus Memory Sourcing
  1. Topics
  2. Cache Coherency
  3. Transactions
  4. Forwarding Versus Memory Sourcing
  5. Three-Hop Versus Four-Hop

Part 3 · Transactions · All levels

Three-Hop Versus Four-Hop

Compare direct and H-buffered exclusive-permission transfers: legs on C1's critical path, completion tracking and when the direct route loses.

On this page

    Which hop are we counting?

    Here a hop is one sender-to-receiver message leg, not one router crossing. We count the legs on the requester's critical path: the messages that must happen, one after another, before C1 can use the line.

    Both traces start from the same checkpoint: X started at 0, C0 acquired M and stored 1. Now C0 M / 1, C1 I / -, H exclusive(C0), memory = 0. The protocol is MSI. C1 wants to write, so C0 must give up exclusive permission and its newest value.

    Three hops: C0 sends Data straight to C1

    C1 requests write permission, H forwards to C0, C0 invalidates its copy and sends one with M permission directly to C1.
    Three legs on C1's critical path. H forwards and C0 sends Data with M permission straight to C1.

    Step

    C0 state / value

    C1 state / value

    H directory

    Memory

    Newest data

    D0. Checkpoint

    M / 1

    I / -

    exclusive(C0)

    0

    C0: 1

    D1. GetM at H

    M / 1

    IM^D / -

    exclusive(C0), pend GetM C1

    0

    C0: 1

    D2. Fwd-GetM at C0

    I / -

    IM^D / -

    exclusive(C0), pend GetM C1

    0

    Data(1) in flight to C1

    D3. Data at C1

    I / -

    M / 1

    exclusive(C0), pend GetM C1

    0

    C1: 1

    (assumed) grant delivered

    I / -

    M / 1

    exclusive(C1)

    0

    C1: 1

    In this variant no message tells H that C1 received Data. As on the course-model page, the model simply assumes H can tell, and H starts no conflicting transaction for X until then. A real protocol needs either a completion message from C1 (off C1's critical path, so C1 still uses the line after three legs) or a rule that C1 holds an early Fwd or Inv until its Data arrives (Part 4).

    Four hops: Data goes through H

    C0 gives up its copy and returns one to H, which then grants it to C1 with M permission.
    Four legs on C1's critical path. H receives the data before it sends the final grant.

    Step

    C0 state / value

    C1 state / value

    H directory

    Memory

    Newest data

    B0. Checkpoint

    M / 1

    I / -

    exclusive(C0)

    0

    C0: 1

    B1. GetM at H

    M / 1

    IM^D / -

    exclusive(C0), pend GetM C1

    0

    C0: 1

    B2. Fwd-GetM at C0

    I / -

    IM^D / -

    exclusive(C0), pend GetM C1

    0

    Data(1) in flight to H

    B3. Data at H

    I / -

    IM^D / -

    exclusive(C0), pend GetM C1

    0

    Data(1) in flight to C1

    B4. Data at C1

    I / -

    M / 1

    exclusive(C0), pend GetM C1

    0

    C1: 1

    (assumed) grant delivered

    I / -

    M / 1

    exclusive(C1)

    0

    C1: 1

    In both routes C0 stops writing before C1's grant is usable, and the value 1 is always in exactly one place. Memory stays stale in both, which is legal: C1 is now the dirty holder. The three-hop route is faster because the completion leg, when a real protocol adds one, is off C1's critical path: C1 uses the line after three legs, and only H waits for the fourth message.

    When does the direct route win?

    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
    def lat(legs, d):
        return sum(d[l] for l in legs)
    
    DIRECT = ["c1h", "hc0", "c0c1"]
    BUFFERED = ["c1h", "hc0", "c0h", "hc1"]
    LEGS = ["c1h", "hc0", "c0c1", "c0h", "hc1"]
    
    equal = {l: 1 for l in LEGS}
    assert len(DIRECT) == 3 and len(BUFFERED) == 4
    assert lat(DIRECT, equal) < lat(BUFFERED, equal)
    
    for c0c1 in range(1, 10):
        for c0h in range(1, 5):
            for hc1 in range(1, 5):
                d = {"c1h": 2, "hc0": 2, "c0c1": c0c1, "c0h": c0h, "hc1": hc1}
                direct_wins = lat(DIRECT, d) < lat(BUFFERED, d)
                assert direct_wins == (c0c1 < c0h + hc1)
    
    congested = {"c1h": 2, "hc0": 2, "c0c1": 7, "c0h": 2, "hc1": 2}
    assert lat(DIRECT, congested) > lat(BUFFERED, congested)
    
    def c1_ready(legs, d):
        k = legs.index("c0c1") if "c0c1" in legs else legs.index("hc1")
        return lat(legs[:k + 1], d)
    
    with_done = DIRECT + ["c1h_done"]
    d_done = dict(equal, c1h_done=1)
    assert len(DIRECT) == 3 and len(with_done) == 4
    assert c1_ready(with_done, d_done) == c1_ready(DIRECT, equal) == 3
    assert lat(with_done, d_done) == 4
    print("PASS: direct wins iff d_c0c1 < d_c0h + d_hc1, completion is off C1's path")

    Fewer legs usually wins: with similar delays on every leg, the direct route saves one leg on C1's critical path, and adding a completion message does not take that saving away. The direct route loses only when the C0-to-C1 leg is slower than the two legs through H, as in the congested case. Its real costs are elsewhere: H must track completion, and C1 must handle races such as a Fwd or Inv that arrives before its Data.

    Common pitfall

    Treating direct cache-to-cache Data as permission for a cache to grant exclusive permission on its own. H decided the transfer by forwarding the request, and C0 must give up its own permission before C1's grant is usable.

    Interview

    Say whether you count critical-path legs, all messages or router hops. Then say how H learns the transfer finished, and whether that message is on the requester's critical path.

    Check yourself Does the three-leg trace show how H learns that the transfer finished?

    No. It assumes H can tell, as the course model does. A real protocol adds a completion message from C1, off C1's critical path, or lets C1 hold an early Fwd or Inv until its Data arrives.

    Related topics

    • Shared course model

    • Choose the source before the route

    Previous

    32 / 167

    Next: When Memory Is Stale

    Up next

    Up nextWhen Memory Is Stale

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Who May Supply Data?