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
  • Real Protocols12
    • MESI Versus MOESI Trade-Offs
    • CHI and ACE Message Models
      • ACE on the Course Model
      • CHI Nodes and Channels
      • CHI Transaction Walkthroughs
      • Mapping ACE and CHI States
    • TileLink and Custom Coherence Extensions
  • SoC Integration12
  • Power, Clocking and Reliability12
  • Verification12
  • Debug and Bring-up12
  • Interview and Design Review17
  • Capstone: A Coherent Model Lab5
Loading lesson

‹CHI and ACE Message Models
  1. Topics
  2. Cache Coherency
  3. Real Protocols
  4. CHI and ACE Message Models
  5. CHI Nodes and Channels

Part 8 · Real Protocols · All levels

CHI Nodes and Channels

CHI (IHI 0050 Issue E.a): RN-F, RN-D, RN-I, HN-F, HN-I, SN-F and MN, the REQ, RSP, SNP and DAT channels, TxnID and DBID, and request retry with RetryAck and PCrdGrant.

On this page

    Who are C0, C1 and H in CHI?

    CHI is a packet protocol between nodes, not a set of point-to-point buses. Each node has a type; the course actors map onto three of them. Names and rules here are from the AMBA 5 CHI Architecture Specification, Arm IHI 0050, Issue E.a, section 1.6 (component naming).

    Node

    Role in the specification

    Course actor

    RN-F

    Fully coherent request node: has a hardware-coherent cache, may issue every transaction, receives every snoop

    C0, C1

    RN-D

    IO-coherent request node with no coherent cache, receives DVM transactions

    None (an IO device)

    RN-I

    IO-coherent request node with no coherent cache, no DVM, no snoops

    None (for example a DMA engine)

    HN-F

    Fully coherent home node: the point of coherence, snoops RN-Fs, consolidates responses, expected to be the point of serialization, may hold a snoop filter or directory

    H

    HN-I

    Non-coherent home for IO, no point of coherence

    None

    SN-F

    Memory-side node for Normal memory, answers requests from the home

    Memory (shown as a Note at H)

    MN

    Miscellaneous node that handles DVM operations

    None

    Four channels, one per message class

    Channel

    Carries

    Course message class

    REQ

    Requests: ReadShared, ReadUnique, CleanUnique, WriteBackFull, and requests from home to SN-F

    Requests (GetS, GetM, Put)

    SNP

    Snoops from home to RN-F: SnpShared, SnpSharedFwd, SnpCleanInvalid and others

    Forwards (Fwd-GetS, Fwd-GetM, Inv)

    RSP

    Responses without data: snoop responses, CompAck, Comp, CompDBIDResp, RetryAck, PCrdGrant

    Responses (Inv-Ack, Put-Ack, completion)

    DAT

    Responses with data: CompData, SnpRespData, CopyBackWrData, NCBWrData

    Responses (Data)

    The split is the deadlock rule from Message Classes and Virtual Networks: responses must always sink. Each channel has its own link-layer credits (L-Credits, one per flit buffer per hop), so a full REQ queue cannot block a snoop response or CompAck behind it. CHI states the endpoint half of the rule too: section 4.11.1 requires an RN-F to answer snoops promptly with no protocol-layer dependency on the completion of its own outstanding requests. Only REQ has a rejection mechanism, which is what keeps the request class from clogging.

    Transaction identifiers

    Every request carries SrcID and TgtID for routing and a TxnID that must be unique among that requester's outstanding requests. In Issue E.a TxnID is 12 bits and a requester may have at most 1024 transactions outstanding (section 2.5). The completer can hand back its own identifier, DBID; the requester then uses it as the TxnID of its CompAck or write data, so the home can find its tracker entry without searching. Forwarding snoops also carry FwdNID and FwdTxnID, so the snooped RN-F can address CompData to the original requester with the requester's own TxnID.

    Retry: RetryAck and PCrdGrant

    Section 2.11 defines request retry. A first attempt is sent with AllowRetry set. A completer that cannot accept it returns RetryAck with a PCrdType and records the requester. When resources free up it sends PCrdGrant, a protocol credit of that type. The requester resends with AllowRetry deasserted and the same PCrdType, and that attempt is guaranteed to be accepted. A PCrdGrant may arrive before the RetryAck it belongs to, so the requester must remember a credit it cannot yet use. This is the reserved-retry remedy for starvation from Retries, NACKs and Credits: the credit, not luck, guarantees the second attempt.

    Worked case on the course model: X started at 0 in memory and in no cache. H's trackers are all busy with other lines when C1 reads X.

    C1's first ReadShared is refused with RetryAck, H later grants a protocol credit, C1 resends without AllowRetry, H reads memory and returns the line unique clean, and C1 acknowledges.
    A retried CHI read. The second attempt uses the granted credit and cannot be refused.

    Step

    C0 state / value

    C1 state / value

    H directory

    Memory

    Newest data

    (assumed) H trackers busy with other lines

    I / -

    I / -

    U

    0

    memory: 0

    1. ReadShared at H, refused

    I / -

    IS^D / -, request kept for retry

    U

    0

    memory: 0

    2. RetryAck at C1

    I / -

    IS^D / -, request kept for retry

    U

    0

    memory: 0

    3. PCrdGrant at C1

    I / -

    IS^D / -, credit held

    U

    0

    memory: 0

    4. ReadShared at H, accepted

    I / -

    IS^D / -

    U, pend ReadShared C1

    0

    memory: 0

    H reads memory

    I / -

    IS^D / -

    U, pend ReadShared C1

    0

    memory: 0, Data(0) in flight to C1

    5. CompData_UC at C1

    I / -

    UC / 0

    U, pend ReadShared C1

    0

    C1 and memory: 0

    6. CompAck at H

    I / -

    UC / 0

    exclusive(C1)

    0

    C1 and memory: 0

    UC is the CHI name for E: with no other holder, a ReadShared may be answered unique clean, as in the spec's Figures 5-1 and 5-2 (there the data comes straight from SN-F by Direct Memory Transfer (DMT: the memory node sends CompData straight to the requester)). The check below models the requester side, including the early credit.

    example.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    def run(events, keep_early_credit=True):
        st = {"pending": True, "retry": False, "credit": None, "accepted": False}
        for ev, arg in events:
            if ev == "RetryAck":
                st["retry"] = True
                if st["credit"] == arg:
                    st["accepted"] = True       # resend with AllowRetry=0
            elif ev == "PCrdGrant":
                if st["retry"]:
                    st["accepted"] = True
                elif keep_early_credit:
                    st["credit"] = arg          # remember it for the RetryAck
        return st["accepted"]
    
    normal = [("RetryAck", 0), ("PCrdGrant", 0)]
    early = [("PCrdGrant", 0), ("RetryAck", 0)]
    assert run(normal)
    assert run(early)
    assert not run(early, keep_early_credit=False)   # credit dropped, request starves
    assert not run([("RetryAck", 0)])                # no credit yet, must wait
    print("PASS: a resend needs a credit, and an early PCrdGrant must be kept")

    Common pitfall

    Treating PCrdGrant as permission to use the line. It only promises that a resent request will be accepted. Coherence permission still arrives with CompData or Comp, as in the course model.

    Interview

    Map the four CHI channels to the three course message classes and explain which one may be refused and why the others must always sink.

    Check yourself Could CHI let the home refuse a snoop response with RetryAck when its buffers are full?

    No. Retry is defined only for requests. A snoop response completes work the home already accepted. If the home could refuse it, a full request queue could stop the response that would free a tracker, which is the protocol deadlock from Part 5. The home must reserve space for the responses its outstanding snoops can cause.

    Related topics

    • Shared course model

    • Part 5: responses always sink

    • Part 4: retries and credits

    • Next: CHI walkthroughs

    Previous

    91 / 167

    Next: CHI Transaction Walkthroughs

    Up next

    Up nextCHI Transaction Walkthroughs

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Mapping ACE and CHI States