UCIe · Module 23
UCIe vs Infinity Fabric
Why the most common UCIe comparison is a layer error — a system fabric owns semantics, routing and coherent state while a die-to-die link owns how two dies exchange flits, what fabric-over-transport would require, and the sharpest failure in the module: a transport that preserves every bit and destroys a semantic obligation.
Chapters 23.1 and 23.2 compared things at the same layer. This chapter is about the comparison that is usually not valid at all — and about what the valid version of the question would be.
1. The One-Sentence Model
A system fabric defines semantics and topology: what a request means, where it goes, what ordering and completion it is owed, and how coherent state is maintained. A die-to-die link defines how two dies exchange flits across a package boundary. They are not competitors by default — and "which replaces which?" is a question with no correct answer because the two are not alternatives.
The valid question is a layering question, and 22.2 §11 already framed it: could a proprietary fabric ride over a standardised die-to-die transport, and what would have to be preserved for that to be correct? §11 onward is that question answered properly.
2. What This Chapter Owns
| Question | Where |
|---|---|
| Layer normalisation as a method | 23.1 — UCIe vs PCIe |
| Standard vs private boundary; the organisational argument | 23.2 — UCIe vs Proprietary D2D |
| AMD's public record; the incumbent-fabric problem; layering | 22.2 — AMD Chiplets on UCIe |
| Cache coherency, snooping, directories | CHI Module 1–2 |
| Coherence across a die boundary; identity; ordering | 22.4 — Data-Centre Processors |
| Error recovery, epochs, reconciliation | 14.2 · 21.4 |
| Package-local vs accelerator scale-up scope | 23.4 (next) |
Three things are new here:
The layer error made explicit (§5–§7), with the two stacks drawn so the mismatch is visible rather than argued.
What "fabric over transport" would require (§11–§13) — four properties that must survive, and the RTL boundary that either preserves them or does not.
And the module's sharpest failure (§14–§15): a transport that delivers every bit correctly and destroys a semantic obligation, producing an orphaned transaction that no bit-level check can detect.
3. Sourcing and Evidence Limits
4. Claim-vs-Evidence
| Claim | Evidence | Level | Source / date | Proves | Does not prove |
|---|---|---|---|---|---|
| AMD is among UCIe's co-developers | Consortium composition | A (record) | Aug 2026 | participation in creating the standard | nothing about AMD products |
| AMD publicly supports UCIe as an ecosystem direction | CTO Papermaster on supporting industry standards and UCIe's ecosystem role | C | attributed, via 22.2 §4 | a public commercial position | no product, no link, no date |
| AMD states intent to use UCIe in future products | reported roadmap framing | C | 22.2 §4 | stated intent | not implementation, not a schedule |
| Infinity Fabric is central to AMD's multi-die products | named as enabling EPYC, Ryzen, Instinct MI300-series | C/E | widely documented | the fabric's architectural role | nothing about UCIe |
| AMD maintains a named Infinity Fabric roadmap | FAD 2025 slide "AMD Infinity Fabric Roadmap" | C (primary, partial read) | AMD FAD 2025 | the fabric has a forward roadmap | its relationship to UCIe — §3's caveat |
| AMD runs Infinity Fabric over UCIe | none found | — | — | — | §12 is architectural possibility, Level E |
| A shipping AMD product uses UCIe D2D | none found | — | — | — | — |
Three readings.
Rows 2 and 3 are Level C and are about UCIe; rows 4 and 5 are Level C and are about the fabric. No row connects them — which is precisely the gap §12 must not fill by inference.
Row 6 is the row this chapter exists to keep empty. It is the claim the comparison invites, and I found nothing establishing it.
And row 5's parenthetical matters. A partial extraction that did not surface "UCIe" is not evidence that the roadmap excludes it. Reporting the absence as a finding would be the error 21.7 §11 is about.
5. Two Stacks, Different Heights
Three things to read.
The fabric occupies four rows; the link occupies two. They meet on one. Any comparison that treats them as alternatives is implicitly claiming the fabric's top three rows do not exist.
Everything above the boundary is fabric-owned and everything below is link-owned — and that division is the entire content of §6 and §7.
And the boundary row is where the interesting question lives (§12). Not "which one wins?" but "if the fabric selected this transport, what would have to be preserved?"
6. What a Fabric Owns
| Responsibility | Why a link cannot own it |
|---|---|
| what a request means | a link carries bits; meaning is protocol |
| coherence state | a distributed protocol across many participants (CHI) |
| routing and topology | the link connects two dies; a fabric spans many |
| ordering domains | a system-wide property (22.4 §13) |
| transaction identity and lifetime | outstanding work spans multiple hops (22.4 §10) |
| completion guarantees | a system contract, not a per-hop one |
| deadlock freedom | a property of the whole graph (13.3) |
And rows 3 and 7 are the ones that make the layer difference concrete. A die-to-die link is, by construction, point to point between two dies. Routing and deadlock freedom are properties of a graph — so no amount of link capability can supply them, and a system with several dies needs something above the links whatever those links are.
7. What a Die-to-Die Link Owns
| Responsibility | Scope |
|---|---|
| moving flits across one package boundary | two dies |
| framing | per-transfer |
| optional integrity and retry | per-link (19.3) |
| link training, configuration, recovery | per-link (21.2) |
| carrying a protocol layer above it | defined for the mapped protocols |
And the last row is the connection between the two tables. A die-to-die specification defines how a protocol is carried, not what the protocol means — which is 23.1 §7's "what it deliberately does not define", now the central point rather than a footnote.
8. Why "Replace" Is the Wrong Question
WRONG: "Will UCIe replace Infinity Fabric?"
Why it has no answer: the two occupy different rows (§5). Replacing a
fabric with a link would leave nothing owning coherence, routing,
ordering, identity, completion or deadlock freedom.
BETTER QUESTIONS:
1. Could a standardised D2D transport carry a proprietary fabric's
messages across a package boundary? -> §12
2. Which fabric semantics would have to be preserved for that to be
correct? -> §11
3. Which parts of the fabric remain proprietary regardless? -> §6
4. At WHICH die boundary would that trade be worth making? -> 23.2 §8Two properties.
Question 4 is 23.2's organisational question, which means this chapter's conclusion is boundary-by-boundary rather than technology-versus-technology.
And question 1 is a genuine architectural possibility, not a claim about anyone's product. 22.2 §11–§12 establishes that UCIe's layer separation permits a proprietary protocol above a standard PHY — Raw Mode or a Streaming path — with who owns reliability as the consequence. That is a statement about the standard's structure. It is not a statement about AMD (§3, §4 row 6).
9. The Layer Error, Concretely
| Comparison as usually posed | What it actually compares | Verdict |
|---|---|---|
| "fabric bandwidth vs UCIe bandwidth" | an aggregate system property vs a per-link property | invalid |
| "fabric latency vs UCIe latency" | end-to-end, multi-hop vs one boundary crossing | invalid |
| "which is more open?" | a vendor architecture vs a consortium standard | valid but not a performance question |
| "which owns coherence?" | — | valid — and the answer is the fabric (§6) |
| "could one carry the other?" | — | valid, and the useful question (§12) |
And rows 1 and 2 are worth naming precisely because they are how the comparison is almost always presented: a fabric number is a property of a graph and a link number is a property of an edge. They do not measure the same thing, so no arithmetic relates them — which is why §3 states no figure for either.
10. Coherence Ownership
The coherence protocol owns the semantic state. A transport carries its messages. Nothing I could reach establishes that UCIe defines CPU cache coherence, and this chapter does not claim it (§3).
What a transport must nonetheless guarantee for a coherence protocol above it to remain correct (22.2 §14, 22.4 §9):
| Requirement | Consequence if violated |
|---|---|
| ordering within a domain | the protocol's correctness argument fails |
| no silent drop | a hang, not a retry — a blocked participant never unblocks |
| guaranteed completion | a core or agent waits indefinitely |
| bounded latency | the system stalls rather than slows |
| obligation survival across recovery | §14 — the sharpest failure |
And the fifth row is the one that does not appear in a bit-level specification at all, which is exactly why §14 is possible.
11. Illustrative — A Fabric Message
// ILLUSTRATIVE ONLY. A generic fabric message: everything a SYSTEM-level
// protocol needs, expressed with no reference to any transport.
typedef enum logic [3:0] {
FAB_REQ, FAB_SNOOP, FAB_RESP, FAB_COMPLETE, FAB_WRITEBACK
} fab_kind_e;
typedef struct packed {
// IDENTITY — spans multiple hops, so it cannot belong to a transport
logic [SEM_W-1:0] sem_id;
logic [GEN_W-1:0] generation; // 22.4 §12 — which USE of that id
// SEMANTICS — fabric-owned (§6)
fab_kind_e kind;
logic [DOM_W-1:0] order_domain; // ordering scope
logic requires_completion;
// TOPOLOGY — fabric-owned; a point-to-point link cannot supply this
logic [NODE_W-1:0] src_node;
logic [NODE_W-1:0] dst_node;
logic [NODE_W-1:0] home_node; // who owns the coherence decision
// CONTEXT
logic [EPOCH_W-1:0] fab_epoch; // fabric configuration generation
} fab_msg_t;Architecture. Identity, semantics, topology and context in one object — the four things §6 says a fabric owns, and none of them is a transport property.
State. None here; the fabric's outstanding-transaction table holds it.
Cycle/event behaviour. Constructed by the fabric, handed to a transport adapter (§12), and retired only on a fabric-level completion — never on a transport event.
Contract. sem_id + generation identify the operation across every hop it takes. A transport may retransmit, fragment or recover underneath; none of that changes the identity, which is precisely what makes §14's failure a violation rather than a normal event.
Failure. If home_node or order_domain were derived from transport state, the fabric's semantics would depend on which link the message happened to take — §13.
DV/debug. This object is the unit a fabric-level scoreboard correlates on (20.4). A model that tracks transport attempts instead of sem_id cannot distinguish a retry from a duplicate (21.6 §19).
12. Illustrative — Fabric Over Transport
// ILLUSTRATIVE ONLY (§11). The adapter between a fabric and a D2D transport.
// This is §8's question 1 expressed as an interface — an ARCHITECTURAL
// POSSIBILITY, not a claim about any product (§3, §4 row 6).
module fabric_to_d2d_adapter (
input logic clk,
input logic rst_n,
// fabric side
input fab_msg_t fab_msg,
input logic fab_valid,
output logic fab_ready,
output logic fab_delivered, // SEMANTIC delivery, not transmit
output logic [SEM_W-1:0] fab_delivered_id,
output logic [GEN_W-1:0] fab_delivered_gen,
// transport side
output logic [PAY_W-1:0] tx_payload,
output logic tx_valid,
input logic tx_ready,
input logic transport_recovering, // OBSERVED, never acted on (§13)
// the contract term that decides §14
input logic transport_retains_across_recovery
);
// The fabric message is carried OPAQUELY. The adapter does not interpret
// coherence, routing or ordering — those stay fabric-owned (§6).
assign tx_payload = fab_payload_pack(fab_msg);
// Accept only when the transport can take it AND we can record the
// obligation. Accepting without recording is how §14 starts.
assign fab_ready = tx_ready && obligation_slot_free;
assign tx_valid = fab_valid && obligation_slot_free;
// THE CRITICAL RULE: a transport recovery does NOT retire a fabric
// obligation. If the transport does not retain across recovery, the
// adapter must REPLAY or explicitly RECONCILE — never silently drop
// (21.4 §23). Clearing here is §14.
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
for (int i = 0; i < MAX_OBLIG; i++) oblig_live_q[i] <= 1'b0;
end else begin
if (fab_valid && fab_ready) begin
oblig_live_q[alloc_slot] <= 1'b1;
oblig_id_q[alloc_slot] <= fab_msg.sem_id;
oblig_gen_q[alloc_slot] <= fab_msg.generation;
end
// Retire ONLY on an observed fabric-level completion, matched on
// identity AND generation (22.4 §12).
if (fab_completion_fire && oblig_live_q[comp_slot]
&& (oblig_id_q[comp_slot] == fab_completion_id)
&& (oblig_gen_q[comp_slot] == fab_completion_gen))
oblig_live_q[comp_slot] <= 1'b0;
// On recovery exit, replay anything the transport did not retain.
if (recovery_exit && !transport_retains_across_recovery)
replay_pending_q <= oblig_live_q; // NOT a clear — a replay list
end
end
endmoduleArchitecture. An adapter that carries fabric messages opaquely and maintains fabric-level obligations independently of transport events.
State. An obligation table keyed by slot, holding identity and generation, plus a replay list.
Cycle/event behaviour. Allocation on acceptance (fab_valid && fab_ready); retirement only on an observed fabric completion matching identity and generation. Transport recovery touches neither.
Contract. transport_retains_across_recovery is the term 23.1 §16 introduced, and here it decides between two correct behaviours: retain, or replay. What it must never select is "clear" — §14.
Failure. Retiring an obligation on a transport event is §14. Accepting a message without allocating an obligation slot creates an obligation the adapter cannot track — the same orphan, arriving one cycle earlier.
DV/debug. The obligation count is a directly observable silicon quantity (21.7 §21): a count that drops without a matching completion is §14 caught at the cycle it happens, rather than as a hang minutes later.
13. Wrong RTL — Fabric Coupled to Transport State
// WRONG — fabric-level decisions read transport internals. Each line is
// individually reasonable; together they make the fabric unportable AND
// semantically wrong.
always_comb begin
// 1. Routing decided by which physical link is currently trained.
route_dst = (phy_link_up[0]) ? NODE_A : NODE_B;
// 2. Ordering domain derived from the transport's virtual channel.
order_domain = transport_vc_id;
// 3. Completion timeout taken from the transport's retry counter.
completion_due = (transport_retry_count > RETRY_MAX);
// 4. Snoop issue gated on transport recovery state.
issue_snoop = fab_snoop_pending && !transport_recovering;
}What each costs:
| Line | The error | Consequence |
|---|---|---|
| 1 | routing is a fabric property (§6) | a link event silently changes destinations — messages go to the wrong node |
| 2 | ordering domain is a system property | changing transport changes ordering guarantees; 21.6 §14's violation, self-inflicted |
| 3 | a semantic lifetime derived from a transport counter | timeouts become wrong when the transport changes — 23.1 §17 |
| 4 | a coherence action gated on a transport state | a recovery can stall coherence progress, and 13.3's deadlock follows |
Four properties.
Line 1 is the most dangerous and the least obvious. Routing is not a performance choice — it determines which node receives a coherence message. A transport event silently redirecting it corrupts the protocol's state distribution, and no integrity check fires because every bit arrived correctly somewhere.
Line 4 converts a transient into a deadlock. A recovery is bounded; a coherence protocol blocked during it may hold resources that the recovery itself needs.
All four pass every unit test, because in a single-transport design they are consistent.
And the fix is 23.1 §16's: the transport publishes a capability record, and the fabric reads only that. Routing, ordering, lifetime and coherence progress are fabric-owned and must be derived from fabric state.
14. Failure — the Transport Preserves Every Bit and Destroys an Obligation
The sharpest failure in Module 23, because every bit-level check passes.
| Step | Event |
|---|---|
| 1 | fabric issues a coherent request, sem_id = X, generation = 3, awaiting completion |
| 2 | the adapter accepts it and records the obligation |
| 3 | the D2D link takes an event and recovers successfully |
| 4 | the adapter clears its obligation table on recovery — "the link restarted, so start clean" |
| 5 | CRC passes on everything. No bit was corrupted. No integrity check fires. |
| 6 | the fabric is still waiting for X's completion |
| 7 | the home node's coherence state for X's line is now inconsistent with the requester's |
| 8 | eventually sem_id = X is reused with generation = 4 |
| 9 | a late completion for generation 3 arrives and — without generation matching — retires generation 4 |
Five readings.
Step 5 is the whole point. The transport did its job perfectly: every flit that crossed was delivered correctly, and CRC and retry behaved exactly as specified. Transport correctness and protocol correctness are different properties, and no amount of the first supplies the second.
Step 4 is a plausible design decision, not a blunder. "The link recovered, so its state is stale" is reasonable for transport state and catastrophic for semantic obligations — and the two live in the same module unless someone separates them (21.4 §23).
Step 7 is where it becomes a coherence bug rather than a hang: the two ends now disagree about a line's state, which is the failure mode a coherence protocol exists to make impossible.
Step 9 turns it into silent corruption, and is prevented by generation matching (22.4 §12) — the second half of the fix.
And the correct behaviour is §12's: on recovery exit, replay or explicitly reconcile (21.4 §23). Silently forgetting an obligation is not a recovery — it is a lost transaction wearing a recovery's name.
15. Assertions
// MANDATORY. Illustrative architectural properties (§3) — not normative for
// UCIe and not attributed to any fabric.
// (1) A TRANSPORT RECOVERY DOES NOT RETIRE A FABRIC OBLIGATION.
// English: the live-obligation set is unchanged across a recovery, unless a
// fabric-level completion or an explicit reconciliation occurred. Sampled on
// the recovery EXIT edge. This is §14, caught at the cycle it happens.
a_recovery_does_not_retire_obligations: assert property (
@(posedge clk) disable iff (!rst_n)
$fell(transport_recovering)
|-> (oblig_live_q == $past(oblig_live_q, RECOVERY_DEPTH))
|| reconcile_fire
);
// (2) A PHYSICAL RETRY IS NOT A SECOND SEMANTIC REQUEST.
// English: however many times the transport retransmits, the fabric observes
// one request. Catches 21.6 §19's duplicate misreading at the adapter.
a_retry_not_new_request: assert property (
@(posedge clk) disable iff (!rst_n)
transport_retry_fire |-> !(fab_valid && fab_ready)
);
// (3) A PHYSICAL ATTEMPT CANNOT MUTATE A FABRIC IDENTITY.
// English: the semantic id and generation of a live obligation are stable
// until it retires. Catches an adapter that re-tags on retransmission.
a_identity_stable_while_live: assert property (
@(posedge clk) disable iff (!rst_n)
(oblig_live_q[0] && $past(oblig_live_q[0]))
|-> ($stable(oblig_id_q[0]) && $stable(oblig_gen_q[0]))
);
// (4) FABRIC ROUTING DOES NOT DEPEND ON TRANSPORT STATE.
// English: a live message's destination is stable across link events.
// Catches §13 line 1 — the silent redirection no integrity check can see.
a_route_stable_for_live_msg: assert property (
@(posedge clk) disable iff (!rst_n)
(msg_live && $changed(phy_link_up)) |-> $stable(msg_dst_node)
);
// (5) FABRIC EPOCH IS STABLE FOR A LIVE OBLIGATION.
// English: fabric configuration cannot change under an outstanding message.
// 21.6 §27's mid-flight mutation, at fabric level.
a_fab_epoch_stable: assert property (
@(posedge clk) disable iff (!rst_n)
(|oblig_live_q && $changed(fab_epoch_q)) |-> in_fabric_quiesce
);Architecture. Five properties, each protecting one thing a transport must not do to a fabric.
State. The obligation table, identity registers, and the fabric epoch.
Sampled timing. Property (1) samples on $fell(transport_recovering) — the exit edge, because that is when retention is observable; sampling during recovery compares against a transient. Properties (3) and (4) use $stable guarded by liveness so they do not fire on legitimate retirement or reallocation.
Contract. RECOVERY_DEPTH must be derived from the recovery's own duration. A guessed value makes (1) either vacuous or constantly false — 21.6 §29's bounded-window trap.
Failure if omitted. Without (1), §14 ships and presents as a coherence inconsistency with no link error to point at. Without (4), §13's silent redirection is undetectable by any bit-level mechanism — which makes it the highest-value property here after (1).
DV/debug. In silicon these become counters rather than assertions (21.7 §21): an obligation count that drops without a matching completion is (1) in register form, and it is cheap.
16. Performance
Replacing one transport beneath a fabric cannot be assumed to change system performance.
| System performance depends on | Owned by |
|---|---|
| routing and topology | the fabric |
| arbitration and fairness | the fabric |
| where data and coherence homes sit | the system |
| memory service rate | outside both |
| per-hop transport rate and latency | the link |
| number of hops | the topology |
And the reading is 22.3 §9's and 23.2 §16's unchanged: only one row belongs to the link. Improving it changes end-to-end performance only if that row is binding — and in a multi-hop fabric with a memory-bound workload it usually is not.
17. Openness Is a Different Axis
| A vendor system fabric | A consortium D2D standard | |
|---|---|---|
| optimisation goal | one company's systems, end to end | a boundary many parties can implement |
| specification availability | architectural material only (§3) | membership-gated, but a shared document exists |
| who must agree | one company | any two conforming implementations |
| evolution | free, per generation | revision-managed |
And this is 23.2 §1's trade at system scale, not a criticism of either. A fabric optimised end-to-end for one company's systems is doing a different job from a boundary specification designed to be implemented independently — and neither is a deficient version of the other.
18. Common Misconceptions
"UCIe replaces Infinity Fabric." §5, §8: they occupy different rows. Replacing a fabric with a link would leave nothing owning coherence, routing, ordering, identity or deadlock freedom.
"Infinity Fabric is just a PHY." §6: it owns semantics, routing, ordering and identity — four rows a point-to-point link cannot supply.
"UCIe defines coherence." §10: nothing I could reach establishes that. A transport carries a coherence protocol's messages; the protocol owns the state.
"If UCIe carries a fabric message, the fabric becomes standardised." §12: the message is carried opaquely. Semantics, routing and ordering remain proprietary above the boundary.
"A standard transport removes vendor-specific routing." §6, §13: routing is fabric-owned, and deriving it from transport state is a bug (§13 line 1).
"Transport correctness implies protocol correctness." §14: every bit arrived and CRC passed, and a semantic obligation was destroyed.
"Changing transport automatically changes system performance." §16: only one of six rows belongs to the link, and it must be binding for the change to matter.
"Public architecture material equals full specification." §3: AMD publishes architectural role, not protocol internals — and the gap is where inference gets published as fact.
"AMD's UCIe membership proves a shipping product uses it." §4: rows 2–5 are Level C about two different subjects, and no row connects them.
19. Understanding Check
20. Summary
Five things.
A fabric owns four rows and a link owns two, and they meet on one (§5). Coherence, routing, ordering, identity, completion and deadlock freedom are fabric-owned — and no link capability supplies any of them.
So "replace" has no answer (§8). The valid questions are whether a standard transport could carry the fabric, what must be preserved, and at which boundary the trade is worth making.
Transport correctness is not protocol correctness (§14). Every bit can arrive, every CRC can pass, and a semantic obligation can be destroyed — which is the failure no integrity mechanism can detect.
Fabric decisions must never be derived from transport state (§13). Routing from link state is the worst case, because the message is delivered perfectly to the wrong node.
And replacing a transport changes one of six rows (§16). It matters only if that row binds.
On evidence: AMD publishes the fabric's architectural role at Level C/D and not its internals (§3). This chapter states no protocol detail, routing algorithm, wire format, latency or bandwidth figure for it, no numeric comparison of any kind, and no claim that AMD runs its fabric over UCIe — that row of §4 is empty because I found nothing to put in it.