CXL · Module 28
CXL vs Proprietary Fabrics
Openness is a property of the specification, not of the silicon. This chapter builds the capability argument, the reachable set, standardisation lead time, specialisation, second-sourcing, the ecosystem count, the exit cost, where proprietary wins and why most systems use both.
28.3 placed CXL against something at a different layer. This chapter places it against its direct competitors — why use CXL rather than a vendor's own coherent fabric? — and it is the comparison where the usual answer is not a technical claim at all.
It is an open standard. True, and it is where most answers stop: no capability argument, no count of what actually attaches, nothing about how long standardisation takes, nothing about what leaving would cost, and nothing about how many parts exist.
1. The Engineering Problem — Openness Is A Property Of The Specification
Openness says nothing about capability. Ten claims with eight about the specification being published and two about what it does leaves four of six decisions with nothing behind them. Section 5.
The reachable set is what openness actually buys. Twenty parts wanted with six from the vendor and nine implementing the standard is five that cannot attach at all — and it is a count rather than a principle. Section 6.
A standard has a lead time. A need in quarter four, a proprietary answer in five and a ratified standard in eleven is six quarters of waiting, which is longer than some products live. Section 7.
A point solution can specialise. Three times the rate on four of twelve cases is eight cases given up, and the gain is real — it is simply not free. Section 8.
The exit cost is what lock-in means. Twenty blocks with six portable is fourteen to rewrite plus forty software sites, and it is knowable in advance rather than discovered. Section 11.
This chapter against the rest of Module 28, stated precisely. 28.1 and 28.2 compared protocols on what they do; 28.3 compared things at different layers. This one compares two things that do the same job, so the technical axis is narrow and the decisive axes — reach, timing, sourcing, ecosystem, exit — are commercial. That is not a weaker comparison; it is a different kind, and treating it as a technical one is how it goes wrong.
2. The One-Sentence Model
A comparison of CXL against a proprietary fabric is sound when both are named, when a capability argument is made rather than an openness one, when the reachable set is counted, when the standardisation lead time is stated, when the exit cost is computed, and when the ecosystem is counted in shipping parts — and "it is an open standard" is one of those six.
3. What This Chapter Owns
| Ground | Owner |
|---|---|
| CXL against a non-coherent bus | 28.1 |
| CXL against an on-die coherency fabric | 28.2 |
| CXL against a die-to-die transport | 28.3 |
| Which device type to choose | 27.6 |
| CXL against a vendor's own fabric | this chapter |
Some vocabulary, because this comparison is conducted in words that carry commercial rather than technical meaning.
A proprietary coherent fabric is a vendor's own interconnect between its own parts — NVIDIA's NVLink and AMD's Infinity Fabric are the two most widely discussed examples. Each connects that vendor's devices to each other and, in some configurations, to that vendor's host silicon. Their published detail varies and none of them is a multi-vendor standard.
An open standard is one anybody may implement, published by a body whose members agreed it. CXL is that, and the consortium model is the mechanism by which the agreement happens — and by which it takes time, which is section 7.
The reachable set is the parts a given fabric can actually connect. It is the number the openness argument is really about, and section 6 is about counting it rather than asserting it.
And the exit cost is the work required to move off a fabric. It is not a moral property of a vendor; it is a block count and a call-site count, and section 11 says it is knowable in advance.
4. Teaching-Model Boundary
Every model in this chapter is a teaching model, not an account of any real product. It computes the one relationship the section is about and nothing else.
No number in this chapter is a measurement of any named company's fabric. The figures are chosen to make a relationship visible — a lead time of six quarters, a reachable set of fifteen parts in twenty — and they are illustrative throughout. Where a real vendor is mentioned it is only for the publicly established fact that its fabric exists and connects its own parts; nothing here should be read as a performance or roadmap claim about a specific product.
Each model is built twice from one source. A parameter selects between the measured build, which counts what the decision actually rests on, and the openness build, which treats publication as the argument. Every section's headline number is the gap between them.
| The models do | The models do not |
|---|---|
| Compute one axis of the decision | Describe any real product |
| Contrast an openness claim against a counted one | Predict any vendor's performance |
| Saturate and bound every count they publish | Replace a procurement analysis |
| Count how often each build was wrong | Take a side |
5. RTL 1 — Openness Is Not Capability
Start with the category the argument usually lives in, because it is the reason this comparison is so often decided badly in both directions.
Whether a specification is published is a fact about the document. It says nothing about the fabric's bandwidth, its latency, its coherency model, its failure behaviour or its cost. Those are the things a design decision rests on, and a claim about publication supports none of them.
That cuts both ways, which is what makes it worth a model rather than a slogan. "It is open, therefore it is the right choice" and "it is proprietary, therefore it is better engineered" are the same error with opposite signs — both substitute a fact about the document for an argument about the silicon.
// RTL 1 - openness is a property of the specification, not of the silicon.
// Whether a protocol is published says nothing about what it does, how fast it
// is or what it costs, and an answer built entirely of openness claims has
// said nothing about the engineering.
module openness_is_not_capability #(parameter int OPEN_IS_THE_ANSWER = 0) (
input logic clk, rst_n,
input logic evaluate,
input logic [15:0] claims_total, claims_openness, claims_capability, decisions,
output logic [15:0] openness_ok, capability_ok, claims_unbacked, capability_pct,
output logic capability_argued,
output logic [7:0] n_evals, n_unbacked,
output logic capability_err
);
logic [31:0] c_q;
logic [15:0] true_unbacked;
logic truly_unbacked;
assign openness_ok = (claims_openness > claims_total) ? claims_total : claims_openness;
assign capability_ok = (claims_capability > claims_total) ? claims_total : claims_capability;
// A decision needs a capability claim behind it; an openness claim leaves it
// unbacked however many times it is repeated.
assign true_unbacked = (decisions > capability_ok) ? (decisions - capability_ok) : 16'd0;
assign claims_unbacked = (OPEN_IS_THE_ANSWER != 0) ? 16'd0 : true_unbacked;
assign c_q = (decisions == 16'd0) ? 32'd100
: (({16'd0, capability_ok} * 32'd100) / {16'd0, decisions});
assign capability_pct = (c_q > 32'd100) ? 16'd100 : c_q[15:0];
assign capability_argued = (claims_unbacked == 16'd0) && (decisions != 16'd0);
assign truly_unbacked = (true_unbacked != 16'd0);
assign capability_err = evaluate && truly_unbacked && capability_argued;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
n_evals <= 8'd0; n_unbacked <= 8'd0;
end else if (evaluate) begin
n_evals <= n_evals + 8'd1;
if (truly_unbacked) n_unbacked <= n_unbacked + 8'd1;
end
end
endmoduleTen claims with eight about openness and two about capability, supporting six decisions, leaves four decisions with nothing behind them — a third of them supported.
| Fact | Value |
|---|---|
| Claims | 10 |
| About openness | 8 |
| About capability | 2 |
| Decisions resting on them | 6 |
| Unbacked | 4 |
| Supported | 33% |
Figure 1 — the shape of an argument that cannot lose. The upper path's claim is true and stays true no matter what the fabric turns out to do, which is precisely what makes it useless as support: a claim that cannot be contradicted by any measurement cannot distinguish between two options either. The lower path counts the claims that could turn out to be wrong, and the four decisions left over are the ones somebody will make on instinct.
The last case shows the direction the proportion moves as the argument grows. Thirty-five openness claims and five capability ones across twenty decisions is a quarter supported — the larger the case, the more of it openness is carrying, because openness claims are cheap to generate and capability claims are not.
The eighth case is the one the mutation campaign forced and it is worth its place. An over-claim large enough that the percentage does not saturate — twenty capability claims counted against ten that exist, on twenty decisions — reports half supported rather than all. The model counts the claims the argument actually contains, and repeating a claim does not add support.
The fourth case bounds it honestly. An argument supporting no decision reports everything supported, because nothing rests on it — which is what a specification comparison is before anybody is choosing anything, and it is a legitimate thing to write.
The sixth case makes a point about scale that is easy to miss: shrinking the argument does not improve the proportion. One capability claim across three decisions is the same third as two across six.
There is a reason this particular substitution is so stable, and it is worth naming because it is what makes the section a model rather than a complaint. An openness claim is verifiable from a document and costs nothing to make. Anybody can confirm that the CXL specification is published; no measurement, no silicon, no workload. A capability claim costs a benchmark, a simulation or a datasheet comparison, and it can be wrong in public. The cheap claim therefore multiplies and the expensive one does not, and an argument left to grow on its own drifts towards openness the way water finds a slope.
The symmetric failure is equally common and rarely called out. "It is proprietary, therefore the vendor controlled the whole stack and tuned it" is an inference about engineering quality drawn from a licensing fact, and it is exactly as unsupported as the open version. The model does not distinguish which side a claim favours — it only asks whether the claim could be contradicted by a measurement. Both slogans pass the first test and fail the second.
What the section asks for is not neutrality. A design can conclude that openness is decisive, and sections 6, 9 and 10 are the three places where openness cashes out into something countable. The failure is not preferring it; the failure is preferring it instead of counting, and then presenting the preference as though the count had been made.
6. RTL 2 — The Reachable Set
The second thing, and the first one that is actually a number.
What openness buys is parts. A fabric's value to a design is the set of parts that can attach to it, and for a proprietary fabric that set is one vendor's catalogue while for a standard it is whoever implemented it. That is a count, and it is the count the openness argument is gesturing at without making.
The parts that cannot attach are not lost — they need a bridge, a redesign or a different topology, and each of those has a cost.
// RTL 2 - a proprietary fabric connects that vendor's parts. The reachable set
// is the whole of what openness buys, and it is a number rather than a
// principle: how many of the parts a design wants can actually attach.
module vendor_reach #(parameter int ANY_PART_ATTACHES = 0) (
input logic clk, rst_n,
input logic evaluate,
input logic [15:0] parts_wanted, parts_from_vendor, parts_open, workaround_cost,
output logic [15:0] reachable, unreachable, bridge_cost, reach_pct,
output logic all_reachable,
output logic [7:0] n_evals, n_unreachable,
output logic reach_err
);
logic [31:0] r_q, b_q;
logic [15:0] vendor_ok, open_ok, true_reach, true_unreach;
logic truly_unreachable;
assign vendor_ok = (parts_from_vendor > parts_wanted) ? parts_wanted : parts_from_vendor;
assign open_ok = (parts_open > parts_wanted) ? parts_wanted : parts_open;
// A proprietary fabric reaches its own vendor's parts; an open one reaches
// whatever implements the standard. The design wants both sets.
assign true_reach = ((vendor_ok + open_ok) > parts_wanted)
? parts_wanted : (vendor_ok + open_ok);
assign reachable = (ANY_PART_ATTACHES != 0) ? parts_wanted : true_reach;
assign true_unreach = parts_wanted - true_reach;
assign unreachable = (ANY_PART_ATTACHES != 0) ? 16'd0 : true_unreach;
// Every part that cannot attach directly needs a bridge or a redesign.
assign b_q = {16'd0, true_unreach} * {16'd0, workaround_cost};
assign bridge_cost = (b_q > 32'd9999) ? 16'd9999 : b_q[15:0];
assign r_q = (parts_wanted == 16'd0) ? 32'd100
: (({16'd0, true_reach} * 32'd100) / {16'd0, parts_wanted});
assign reach_pct = r_q[15:0];
assign all_reachable = (unreachable == 16'd0) && (parts_wanted != 16'd0);
assign truly_unreachable = (true_unreach != 16'd0);
assign reach_err = evaluate && truly_unreachable && all_reachable;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
n_evals <= 8'd0; n_unreachable <= 8'd0;
end else if (evaluate) begin
n_evals <= n_evals + 8'd1;
if (truly_unreachable) n_unreachable <= n_unreachable + 8'd1;
end
end
endmoduleTwenty parts wanted with six from the vendor and nine implementing the standard reaches fifteen — five that cannot attach at all, at two hundred and fifty units of bridging.
| Fact | Value |
|---|---|
| Parts wanted | 20 |
| From the vendor | 6 |
| Implementing the standard | 9 |
| Reachable | 15 |
| Unreachable | 5 |
| Reached | 75% |
The last case is the boundary and it is the practical form of the argument. One part in twenty out of reach is enough to make "everything attaches" false, and on a real bill of materials that one part is usually the one with no alternative — a specific accelerator, a specific memory device, the thing the product exists to include.
The fifth case is the state that decides against both options. Neither the vendor nor the standard supplies anything the design wants, which means the parts list and the fabric choice were made by different people and have not been reconciled. That is a procurement failure rather than an architecture one, and it is visible immediately from this count.
The second case is what a healthy standard looks like: enough parts implementing it that the design's whole list is reachable, at no bridging cost — and it is worth noticing that the model does not care which of the two supplied them.
The degenerate case bounds it: a design that wants no parts reaches everything, which is an unwritten parts list rather than a reachable set.
Note what the model does not do with the five unreachable parts: it does not call the design impossible. It attaches a bridging cost, because that is what actually happens. A part outside the fabric's reach gets a bridge, a protocol converter, a second link on the board, or a redesign that removes the need for it — and each of those is a real engineering response with a real price. The openness argument's error is not claiming the parts attach; it is never producing the five.
The bridging figure deserves one caution. Fifty units per part is a teaching number and the real cost is wildly uneven: a bridge that already exists as a shipping component is cheap, and one that has to be designed is a project. What the model is doing is forcing the cost to appear on the sheet at all, because a cost recorded at the wrong magnitude still gets scrutinised and a cost recorded nowhere does not.
And the count is time-varying in one direction, which is section 10's subject and worth flagging here. The nine parts implementing the standard today is a lower bound on the nine implementing it in two years. The six from the vendor is not similarly guaranteed to grow, but it is not guaranteed to shrink either. A reachable set computed once at the start of a programme and never revisited is the most common way this count goes stale, and the fix is to recompute it at each major milestone rather than to guess at the growth.
7. RTL 3 — A Standard Has A Lead Time
The third thing, and the one that most often decides the answer in the proprietary direction.
A consortium standard is an agreement, and agreements take time. A capability is proposed, argued, specified, ratified and then implemented — and a vendor who controls both ends of a link can ship the same capability as soon as its own silicon is ready. The gap between those two dates is measured in product cycles.
A design that needs the capability inside the gap cannot wait for the standard, and no amount of preferring openness changes the calendar.
// RTL 3 - a proprietary fabric can ship a capability before any standard has
// ratified one, and the gap is measured in product cycles. An answer that
// treats standardisation as free has not priced the waiting.
module standard_lag #(parameter int STANDARDS_ARRIVE_ON_TIME = 0) (
input logic clk, rst_n,
input logic evaluate,
input logic [15:0] need_quarter, prop_quarter, ratified_quarter, revenue_per_q,
output logic [15:0] prop_gap, open_gap, gap_quarters, revenue_lost,
output logic no_waiting,
output logic [7:0] n_evals, n_waiting,
output logic lag_err
);
logic [31:0] l_q;
logic [15:0] true_gap, true_lost;
logic truly_waiting;
// How long after the need each option could actually be shipped.
assign prop_gap = (prop_quarter > need_quarter) ? (prop_quarter - need_quarter) : 16'd0;
assign open_gap = (ratified_quarter > need_quarter) ? (ratified_quarter - need_quarter) : 16'd0;
assign true_gap = (open_gap > prop_gap) ? (open_gap - prop_gap) : 16'd0;
assign gap_quarters = (STANDARDS_ARRIVE_ON_TIME != 0) ? 16'd0 : true_gap;
assign l_q = {16'd0, true_gap} * {16'd0, revenue_per_q};
assign true_lost = (l_q > 32'd9999) ? 16'd9999 : l_q[15:0];
assign revenue_lost = (STANDARDS_ARRIVE_ON_TIME != 0) ? 16'd0 : true_lost;
assign no_waiting = (gap_quarters == 16'd0) && (need_quarter != 16'd0);
assign truly_waiting = (true_gap != 16'd0);
assign lag_err = evaluate && truly_waiting && no_waiting;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
n_evals <= 8'd0; n_waiting <= 8'd0;
end else if (evaluate) begin
n_evals <= n_evals + 8'd1;
if (truly_waiting) n_waiting <= n_waiting + 8'd1;
end
end
endmoduleA need in quarter four with a proprietary answer in five and a standard ratified in eleven is six quarters of waiting, and eighteen hundred units of whatever the product earns in that window.
| Fact | Value |
|---|---|
| Need | Q4 |
| Proprietary answer | Q5 |
| Ratified standard | Q11 |
| Proprietary gap | 1 quarter |
| Standard gap | 7 quarters |
| Waiting | 6 quarters |
Figure 2 — the cost that the openness argument never carries a line item for. Neither path is wrong about what the standard will eventually deliver; they differ on when. Six quarters is longer than many products are on sale, which means the comparison is frequently not between two fabrics for one product but between shipping one product now and a different one later.
The fifth case is the direction the argument does go sometimes, and it is worth keeping so the section is not an argument against standards. A standard ratified before the proprietary answer ships gives no waiting at all — which happens when a capability was anticipated rather than reacted to, and it is exactly what a well-run consortium is for.
The sixth case separates the wait from its price. A wait with no revenue attached to it is still six quarters, and the model reports it — because whether the delay was costed is a separate question from whether it exists, and a programme that has not costed it has still incurred it.
The last case is the shape that decides a generation. Seventeen quarters between the two answers is longer than a product cycle, and at that separation the comparison stops being a choice and becomes a sequence: ship on the proprietary fabric, move to the standard at the next generation if it is worth it.
The degenerate case bounds it: a comparison with no need date reports the same six quarters between the two answers and declines to call it a wait, because nobody is waiting for a capability nobody has dated.
The asymmetry the model captures is structural rather than cultural. A vendor that owns both ends of a link needs agreement from nobody: it specifies, implements and ships on one schedule. A consortium needs agreement from members with different products, different roadmaps and sometimes directly opposed interests, and the agreement is the thing that takes the time. That is not inefficiency — it is the mechanism that later produces the multiple implementations section 9 counts. The lead time and the second source are the same process seen at two moments.
Which means the two cannot be traded against each other by wishing. A programme cannot have the ratification speed of a single vendor and the supplier count of a standard, and an argument that implicitly assumes both is describing a fabric that does not exist.
The ratified date also deserves an explicit uncertainty, which section 20 records. A proprietary ship date is a commitment from one company; a ratification date is a forecast about a committee, and the second is the softer of the two. A programme that plans against a ratification date should carry it with a band rather than a point, and should ask what happens to the schedule at the pessimistic end — because the case that decides a generation is exactly the one where the band's far edge crosses the product window.
8. RTL 4 — A Point Solution Can Specialise
The fourth thing, and the one where the proprietary side has a genuine technical argument.
A fabric built for one vendor's two parts can assume things a standard cannot. It can assume the topology, the clocking, the memory model, the error rates, the software stack — every assumption removes a case the design would otherwise have to handle, and removing cases buys rate, latency or area.
A general standard is paying for the cases it handles, and where a design does not need them the payment returns nothing. That is a real trade, and pretending it does not exist is how the openness argument loses credibility with the people who have measured both.
// RTL 4 - a point solution can specialise. A fabric built for one vendor's
// two parts can assume things a general standard cannot, and the gain is real
// - but it is paid for in the generality the standard was buying.
module specialisation_gain #(parameter int GENERALITY_IS_FREE = 0) (
input logic clk, rst_n,
input logic evaluate,
input logic [15:0] gbps_open, gbps_prop, cases_open, cases_prop,
output logic [15:0] speed_gain, cases_lost, gain_pct, cases_ok,
output logic gain_is_free,
output logic [7:0] n_evals, n_traded,
output logic trade_err
);
logic [31:0] g_q;
logic [15:0] true_gain, true_lost;
logic truly_traded;
assign true_gain = (gbps_prop > gbps_open) ? (gbps_prop - gbps_open) : 16'd0;
assign speed_gain = true_gain;
// The cases a general standard handles that the point solution does not.
assign cases_ok = (cases_prop > cases_open) ? cases_open : cases_prop;
assign true_lost = cases_open - cases_ok;
assign cases_lost = (GENERALITY_IS_FREE != 0) ? 16'd0 : true_lost;
assign g_q = (gbps_open == 16'd0) ? 32'd999
: (({16'd0, gbps_prop} * 32'd100) / {16'd0, gbps_open});
assign gain_pct = (g_q > 32'd999) ? 16'd999 : g_q[15:0];
assign gain_is_free = (cases_lost == 16'd0) && (cases_open != 16'd0);
assign truly_traded = (true_lost != 16'd0);
assign trade_err = evaluate && truly_traded && gain_is_free;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
n_evals <= 8'd0; n_traded <= 8'd0;
end else if (evaluate) begin
n_evals <= n_evals + 8'd1;
if (truly_traded) n_traded <= n_traded + 8'd1;
end
end
endmoduleTwo hundred gigabits against sixty-four, on four of twelve cases, is three times the rate and eight cases given up — and the generality-is-free view reports the gain with nothing against it.
| Fact | Value |
|---|---|
| Standard rate | 64 |
| Point-solution rate | 200 |
| Gain | 136 |
| Cases the standard handles | 12 |
| Cases the point solution handles | 4 |
| Given up | 8 |
The second case is the one that makes the trade a measurement rather than an assumption. A point solution that handles every case anyway gives up nothing and keeps the gain, and the model says the gain really is free. That configuration exists — a narrow problem where the general cases genuinely do not arise — and it is the strongest version of the proprietary argument.
The sixth case is the direction nobody expects and it is worth including. A point solution that is slower than the general standard has specialised and has nothing to show for it, which happens when the specialisation was for something other than rate — area, power, or time to market — and the rate comparison was made anyway.
The last case is the sharpest form. A point solution that handles none of the general cases gives up all twelve for its gain, which is what a fabric built for exactly one topology looks like when a second topology arrives.
The fifth case is the honest limit of the measurement. A general standard with no measured rate saturates the ratio and leaves the cases given up unchanged — an unmeasured baseline does not make the trade vanish, it makes half of it unquantified.
The twelve cases are worth making concrete, because "generality" is otherwise a word rather than a cost. A general standard has to handle topologies it did not choose, devices whose latency it cannot predict, hosts with different memory models, error rates it cannot assume away, and software stacks written by people it will never meet. Each of those is a case in the specification and usually a structure in the silicon — a retry path, a wider credit counter, a negotiation phase, a fallback mode. A point solution that knows the topology can delete the negotiation; one that knows the error rate can size the retry buffer to it rather than to the worst case.
That is where the rate difference comes from, and it is why the trade is real rather than marketing. It is also why the trade is directional: the specialised fabric is fast because of what it assumed, so the moment an assumption stops holding the advantage does not degrade gracefully — it stops applying. The eight cases given up are not eight small risks; they are eight conditions under which the comparison has to be redone.
And the honest reading of the sixth case is a caution about how the gain gets quoted. A specialised fabric that is slower than the general one has not failed — it may have specialised for area, power, pin count or time to market, and the rate comparison was simply the wrong axis. The model reports the gain as negative rather than rejecting the design, which is the correct posture: a specialisation is judged against what it was specialising for, and that has to be stated before the benchmark is chosen.
9. RTL 5 — Second-Sourcing Is A Count
The fifth thing, and the one that turns an argument into a procurement position.
An interface is second-sourceable when more than one supplier implements it. Publication is necessary and not sufficient: a standard that exactly one vendor has built is, for procurement purposes, a single source with a published specification. The useful number is suppliers per interface, not whether the document is available.
That distinction matters because it is the only form of the openness argument that a procurement team can act on.
// RTL 5 - second-sourcing is the procurement half of the argument and it is a
// count rather than a principle. A design can only be second-sourced on the
// interfaces that more than one supplier implements.
module second_source #(parameter int OPEN_MEANS_SOURCED = 0) (
input logic clk, rst_n,
input logic evaluate,
input logic [15:0] interfaces, suppliers_each, open_interfaces, risk_per_single,
output logic [15:0] open_ok, single_sourced, sourced_pct, risk_total,
output logic fully_sourced,
output logic [7:0] n_evals, n_single,
output logic source_err
);
logic [31:0] s_q, r_q;
logic [15:0] true_single, true_risk;
logic truly_single;
assign open_ok = (open_interfaces > interfaces) ? interfaces : open_interfaces;
// An open interface is second-sourceable only if somebody else actually
// implements it; being published is necessary and not sufficient.
assign true_single = (suppliers_each > 16'd1) ? 16'd0 : (interfaces - open_ok);
assign single_sourced = (OPEN_MEANS_SOURCED != 0) ? 16'd0 : true_single;
assign r_q = {16'd0, true_single} * {16'd0, risk_per_single};
assign true_risk = (r_q > 32'd9999) ? 16'd9999 : r_q[15:0];
assign risk_total = (OPEN_MEANS_SOURCED != 0) ? 16'd0 : true_risk;
assign s_q = (interfaces == 16'd0) ? 32'd100
: (({16'd0, open_ok} * 32'd100) / {16'd0, interfaces});
assign sourced_pct = s_q[15:0];
assign fully_sourced = (single_sourced == 16'd0) && (interfaces != 16'd0);
assign truly_single = (true_single != 16'd0);
assign source_err = evaluate && truly_single && fully_sourced;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
n_evals <= 8'd0; n_single <= 8'd0;
end else if (evaluate) begin
n_evals <= n_evals + 8'd1;
if (truly_single) n_single <= n_single + 8'd1;
end
end
endmoduleEight interfaces with three open and one supplier each leaves five single-sourced and six hundred units of supply risk — thirty-seven percent open.
| Fact | Value |
|---|---|
| Interfaces | 8 |
| Open | 3 |
| Suppliers each | 1 |
| Single-sourced | 5 |
| Risk each | 120 |
| Open | 37% |
The second case is the section's whole point and it is one input away from the first. A second supplier takes the single-sourced count to zero, and nothing else changed — not the specification, not the design, not the openness. What converts publication into sourcing is somebody else having implemented it, and that is a market fact rather than a licensing one.
The last case is the boundary and it is the version that bites. One interface of eight left closed single-sources the whole design, because a product cannot ship without all of its interfaces. Seven open interfaces do not compensate for one that is not.
The fifth case is the honest end state of a proprietary choice: nothing open at all, eight single-sourced interfaces and the whole supply in one relationship — which is a position many successful products are in deliberately, and which the model prices rather than condemns.
The degenerate case bounds it: a design with no interfaces enumerated reports everything open, which is an uncounted design rather than a sourced one.
The gap between "open" and "second-sourced" is where most of the confusion in this whole comparison lives, and it is worth stating as a sequence. A specification is published — that is openness. Somebody implements it — that is an implementation. A second party implements it compatibly — that is a second source. Each step takes years and only the last one changes a procurement position, and the openness argument routinely claims the third while only the first has happened.
The model deliberately counts suppliers rather than asking whether the interface is open, and that ordering matters: a proprietary interface with two licensed suppliers is better sourced than an open one with a single implementer. That configuration is rare but not hypothetical, and a model that keyed on openness rather than on supplier count would rank them backwards.
The risk figure is a placeholder for something the model does not attempt. A hundred and twenty units per single-sourced interface treats every interface as equally exposed, and real exposure depends on the supplier's health, the volume commitment, the allocation regime and whether an alternative could be qualified under pressure. The count is the part worth trusting; the price is the part worth arguing about, and a procurement team will have better numbers for the second than any model does.
10. RTL 6 — The Ecosystem Is The Number
The sixth thing, and the one that decides whether openness has paid yet.
A standard's value is the parts that implement it, not the parts it describes. A specification listing thirty device categories with eight in production is a roadmap; a design can only buy the eight. A standard nobody has implemented has all of the openness and none of the benefit, and that is a normal state for a specification in its first years rather than a criticism.
// RTL 6 - the ecosystem is the number the openness argument is actually
// about. A standard's value is the parts that implement it, and a standard
// nobody has implemented yet has the openness and none of the benefit.
module ecosystem_size #(parameter int PUBLISHED_IS_POPULATED = 0) (
input logic clk, rst_n,
input logic evaluate,
input logic [15:0] parts_specified, parts_shipping, parts_needed, qual_cost,
output logic [15:0] shipping_ok, parts_missing, populated_pct, qual_total,
output logic ecosystem_ready,
output logic [7:0] n_evals, n_thin,
output logic ecosystem_err
);
logic [31:0] p_q, q_q;
logic [15:0] true_missing;
logic truly_thin;
assign shipping_ok = (parts_shipping > parts_specified) ? parts_specified : parts_shipping;
assign true_missing = (parts_needed > shipping_ok) ? (parts_needed - shipping_ok) : 16'd0;
assign parts_missing = (PUBLISHED_IS_POPULATED != 0) ? 16'd0 : true_missing;
assign q_q = {16'd0, shipping_ok} * {16'd0, qual_cost};
assign qual_total = (q_q > 32'd9999) ? 16'd9999 : q_q[15:0];
assign p_q = (parts_specified == 16'd0) ? 32'd0
: (({16'd0, shipping_ok} * 32'd100) / {16'd0, parts_specified});
assign populated_pct = p_q[15:0];
assign ecosystem_ready = (parts_missing == 16'd0) && (parts_needed != 16'd0);
assign truly_thin = (true_missing != 16'd0);
assign ecosystem_err = evaluate && truly_thin && ecosystem_ready;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
n_evals <= 8'd0; n_thin <= 8'd0;
end else if (evaluate) begin
n_evals <= n_evals + 8'd1;
if (truly_thin) n_thin <= n_thin + 8'd1;
end
end
endmoduleThirty parts specified with eight shipping against twelve needed is four the design needs and cannot buy — a quarter of the specification populated.
| Fact | Value |
|---|---|
| Parts specified | 30 |
| Shipping | 8 |
| Needed by the design | 12 |
| Missing | 4 |
| Populated | 26% |
| Qualification | 480 |
The fifth case is the state the waveform's left-hand side describes. Specified and nothing shipping yet is the openness with none of the benefit — twelve parts missing, nothing to qualify, and a design that cannot be built from the standard however well written it is.
The last case is the shape that decides against a standard on schedule grounds. Five parts shipping against twenty-five needed, with the qualification cost saturating, is an ecosystem that is a roadmap rather than a supply — and a programme that plans against the specification rather than against the shipping list has mis-planned.
The sixth case bounds it from the design's side. A design that needs nothing from the ecosystem cannot find it thin, which is the honest reading for a product using one vendor's parts throughout and consulting the standard only for interoperability it does not need.
The third case is the clamp and it says the expected thing: more parts shipping than the specification describes counts the specified ones, because a part outside the standard is not evidence about the standard.
The interval the waveform shows is the single most underestimated quantity in this comparison, and it is underestimated in a specific way: the specification is treated as the delivery. A programme reads a device category in the standard, puts it in the architecture, and only discovers at procurement that the category has one sampling part from one vendor with a lead time measured in quarters. Nothing was misrepresented — the standard does describe that category — but a specification describes what may be built and a catalogue describes what may be bought, and only the second is a supply chain.
Three practical consequences follow, and they are what makes this section actionable rather than observational. First, the parts list should be built from a catalogue and checked against the standard, not the reverse. Second, the qualification cost is a real line item and it scales with the shipping count, not the specified one — sixty units per part, and a design qualifying eight parts is doing eight qualifications regardless of how open the interface is. Third, the gap closes on its own and the closing rate is observable, so a programme that recorded the shipping count at two milestones has a trend rather than a hope.
The waveform's flat rows are the part to dwell on. The specification did not change across the whole window and neither did the requirement. Every argument about openness made during those six periods was true throughout and made no difference to whether the product could be built — which is the sharpest statement of the chapter's thesis that any single figure in it makes.
11. RTL 7 — The Exit Cost
The seventh thing, and the one that makes lock-in a number instead of a sentiment.
Lock-in is the work required to leave. Not a vendor's intentions, not the licence terms — the count of blocks that would have to be rewritten and call sites that would have to change if the design moved to a different fabric. That number is knowable at design time, and a programme that computes it has converted an anxiety into a budget line.
And it has two columns. The hardware blocks are one; the software written against the fabric's own semantics is the other, and the second is routinely missing from a hardware team's estimate.
// RTL 7 - the exit cost is what lock-in actually means. It is not a moral
// property of a vendor; it is the number of blocks that would have to be
// rewritten to move, and it is knowable in advance.
module exit_cost #(parameter int SWITCHING_IS_A_DECISION = 0) (
input logic clk, rst_n,
input logic evaluate,
input logic [15:0] blocks_total, blocks_portable, block_cost, sw_sites,
output logic [15:0] portable_ok, blocks_rewritten, hw_exit, portable_pct,
output logic exit_is_cheap,
output logic [7:0] n_evals, n_locked,
output logic exit_err
);
logic [31:0] h_q, p_q;
logic [15:0] true_rewritten, true_cost, sw_counted;
logic truly_locked;
assign portable_ok = (blocks_portable > blocks_total) ? blocks_total : blocks_portable;
assign true_rewritten = blocks_total - portable_ok;
assign blocks_rewritten = (SWITCHING_IS_A_DECISION != 0) ? 16'd0 : true_rewritten;
assign h_q = {16'd0, true_rewritten} * {16'd0, block_cost};
assign true_cost = (h_q > 32'd9999) ? 16'd9999 : h_q[15:0];
assign hw_exit = (SWITCHING_IS_A_DECISION != 0) ? 16'd0 : true_cost;
// The software that was written against the fabric's own semantics is a
// separate column, and it is the one a hardware estimate omits.
assign sw_counted = (SWITCHING_IS_A_DECISION != 0) ? 16'd0 : sw_sites;
assign p_q = (blocks_total == 16'd0) ? 32'd100
: (({16'd0, portable_ok} * 32'd100) / {16'd0, blocks_total});
assign portable_pct = p_q[15:0];
assign exit_is_cheap = (blocks_rewritten == 16'd0) && (sw_counted == 16'd0)
&& (blocks_total != 16'd0);
assign truly_locked = (true_rewritten != 16'd0) || (sw_sites != 16'd0);
assign exit_err = evaluate && truly_locked && exit_is_cheap;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
n_evals <= 8'd0; n_locked <= 8'd0;
end else if (evaluate) begin
n_evals <= n_evals + 8'd1;
if (truly_locked) n_locked <= n_locked + 8'd1;
end
end
endmoduleTwenty blocks with six portable and forty software sites is fourteen blocks to rewrite at eleven hundred and twenty units, plus a software column nobody has costed — thirty percent of the design portable.
| Fact | Value |
|---|---|
| Blocks | 20 |
| Portable | 6 |
| To rewrite | 14 |
| Cost each | 80 |
| Hardware exit | 1,120 |
| Software sites | 40 |
The fifth case is the one that makes the second column necessary rather than pedantic. The hardware carries entirely and the software does not — twenty of twenty blocks portable, zero hardware cost, and forty software sites still to change — is reported as a cheap exit by a view that counts blocks, and is not one. A fabric's semantics reach into software, and software written against them is as much of the exit cost as any RTL.
The last case is the far end. Nothing portable costs the design over again, which is the honest description of a deeply integrated proprietary stack and is not automatically the wrong position to be in — it is the position a programme should have chosen deliberately rather than discovered.
The second case is what portability looks like when it was designed for: everything portable and no software written against the fabric, at zero exit cost. That is achievable and it is not free — it usually means an abstraction layer somebody paid for up front.
The degenerate case bounds it: an uncounted design reports everything portable and forty software sites outstanding, which is not portability but an absence of the count.
The reason the software column is routinely missing is organisational rather than technical. A hardware team asked to estimate an exit cost estimates the hardware, because that is the part it owns and can see. The software written against a fabric's semantics — its memory ordering guarantees, its atomics, its failure and recovery model, its management interface — lives in another team's repository and frequently in another company's. The count is not hard to obtain; it is simply nobody's job to obtain it, and the fifth case exists to make the consequence visible.
A second reason the number gets understated is that portability is assessed optimistically. A block that "could be ported" is counted as portable, when what the estimate needs is blocks that require no change. The distinction sounds pedantic and is worth a specific test: if moving the fabric would change the block's timing closure, its buffer sizing or its error handling, it is not portable, even if the interface signals are the same shape.
The value of the number is not the number. It is that a programme holding an exit cost can make a deliberate decision — accept the lock-in, budget the abstraction layer, or negotiate with it on the table — where a programme without one is choosing by temperament. The second case shows the abstraction layer's payoff, and it is worth being clear that the layer is not free: somebody paid for it up front, in schedule and usually in a small amount of performance, and that payment is the premium on an option that may never be exercised.
12. RTL 8 — Where Proprietary Wins
The eighth thing, and the direction an open-standard answer never goes.
A deployment that buys one vendor's parts, runs one vendor's software and has no second source anyway gives up nothing by using that vendor's fabric. The generality a standard sells is real and it is sold to everybody, including the buyers who will never exercise it — and for them it is overhead with no return.
That is the honest reverse case, and an answer that cannot state it is an advertisement rather than an analysis.
// RTL 8 - the comparison has a direction the open-standard answer never goes.
// A deployment that buys one vendor's parts, runs one vendor's software and
// has no second source anyway gives up nothing by using that vendor's fabric,
// and pays the standard's generality for no return.
module where_proprietary_wins #(parameter int OPEN_ALWAYS_WINS = 0) (
input logic clk, rst_n,
input logic evaluate,
input logic [15:0] deployments, single_vendor, open_overhead, gain_each,
output logic [15:0] single_ok, mixed_vendor, overhead_paid, single_pct,
output logic open_everywhere,
output logic [7:0] n_evals, n_wasted,
output logic fit_err
);
logic [31:0] o_q, s_q;
logic [15:0] true_mixed, true_overhead, net_overhead;
logic truly_wasted;
assign single_ok = (single_vendor > deployments) ? deployments : single_vendor;
assign true_mixed = deployments - single_ok;
assign mixed_vendor = (OPEN_ALWAYS_WINS != 0) ? deployments : true_mixed;
// A single-vendor deployment pays the standard's overhead and collects none
// of what the standard was bought for.
// A deployment collects the standard's gain only where it is mixed, so a
// single-vendor one pays the overhead net of a gain it never realises.
assign net_overhead = (open_overhead > gain_each) ? (open_overhead - gain_each) : 16'd0;
assign o_q = {16'd0, single_ok} * {16'd0, net_overhead};
assign true_overhead = (o_q > 32'd9999) ? 16'd9999 : o_q[15:0];
assign overhead_paid = (OPEN_ALWAYS_WINS != 0) ? 16'd0 : true_overhead;
assign s_q = (deployments == 16'd0) ? 32'd0
: (({16'd0, single_ok} * 32'd100) / {16'd0, deployments});
assign single_pct = s_q[15:0];
assign open_everywhere = (overhead_paid == 16'd0) && (deployments != 16'd0);
assign truly_wasted = (true_overhead != 16'd0);
assign fit_err = evaluate && truly_wasted && open_everywhere;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
n_evals <= 8'd0; n_wasted <= 8'd0;
end else if (evaluate) begin
n_evals <= n_evals + 8'd1;
if (truly_wasted) n_wasted <= n_wasted + 8'd1;
end
end
endmoduleTwenty deployments with fourteen single-vendor, at sixty units of overhead against ten of realised gain, is seven hundred units paid for generality those deployments never use.
| Fact | Value |
|---|---|
| Deployments | 20 |
| Single-vendor | 14 |
| Mixed | 6 |
| Overhead each | 60 |
| Gain realised | 10 |
| Paid for nothing | 700 |
The fifth case is the configuration where the objection disappears and it is worth stating. A standard whose overhead its own gain repays costs those deployments nothing net — which is what a well-designed standard achieves, and it is the answer to section 12 rather than a concession to it.
The second case is the standard's own case, stated positively. A wholly mixed estate pays no overhead for nothing, because every deployment exercises the generality it bought. That is the situation the open argument describes and it is a real one — it is simply not every situation.
The last case is the boundary. One single-vendor deployment in twenty is enough to make the sweep false, which is the same shape 28.1 section 12 and 28.2 section 12 both reach: a claim of the form "everywhere" is refuted by one.
The third case is the far end and it is a real estate. Every deployment single-vendor pays a thousand units for generality none of it uses, which is a fleet that standardised on principle rather than on a count.
The overhead is not imaginary and it is worth being specific about what it consists of, because "standards have overhead" is otherwise the same kind of contentless claim this chapter opened by criticising. A general fabric carries negotiation it does not need when both ends are known, credit and retry structures sized for error rates it will not see, mode and capability registers for configurations nobody will select, and a software stack with abstraction layers standing between the workload and hardware whose identity is fixed. Each is silicon, latency or cycles, and a deployment that will never exercise the flexibility pays for all of it.
The fifth case is the answer to the objection rather than a concession to it, and it is the configuration a well-designed standard reaches: the generality's own gain — a better-negotiated link, a wider credit window, an error path that actually fires — repays what it cost. When that holds, the single-vendor deployments are not subsidising anything, and the overhead argument evaporates. The reason to model it rather than assume it is that whether it holds is a measurement, and it differs per fabric and per workload.
The section exists because the reverse case is what makes the rest of the chapter credible. An analysis that produces "use the standard" for every input has not analysed anything, and a reader who has deployed a single-vendor estate knows it. Naming the deployment where the proprietary fabric is correct is the cheapest available demonstration that the other nine sections were counts rather than a position.
13. RTL 9 — Most Large Systems Use Both
The ninth thing, and the one that dissolves the question the chapter opened with.
The two are not mutually exclusive. A large accelerator system commonly has a vendor's own fabric between its accelerators and an open standard to the host and to memory — because the two connections have different requirements, different reachable sets and different exit considerations. A comparison that forces one answer has to discard one of those domains.
// RTL 9 - the two are not mutually exclusive and most large systems use both.
// A design with a proprietary fabric between its accelerators and an open one
// to the host has made two decisions, and a comparison that forces one answer
// has to discard one of them.
module both_at_once #(parameter int ONE_FABRIC_ONLY = 0) (
input logic clk, rst_n,
input logic evaluate,
input logic [15:0] domains, domains_prop, domains_open, bridge_cost,
output logic [15:0] prop_ok, open_ok, domains_unserved, served_pct,
output logic [15:0] bridge_total,
output logic one_answer_serves,
output logic [7:0] n_evals, n_unserved,
output logic both_err
);
logic [31:0] s_q, b_q;
logic [15:0] one_only_served, true_unserved;
logic truly_unserved;
assign prop_ok = (domains_prop > domains) ? domains : domains_prop;
assign open_ok = (domains_open > domains) ? domains : domains_open;
// Forcing one answer serves only the domains that answer suits - the larger
// of the two sets, never their union. That figure is what the design gives
// up, and it does not depend on which view is being built.
assign one_only_served = (prop_ok > open_ok) ? prop_ok : open_ok;
assign true_unserved = domains - one_only_served;
assign domains_unserved = (ONE_FABRIC_ONLY != 0) ? 16'd0 : true_unserved;
assign b_q = {16'd0, true_unserved} * {16'd0, bridge_cost};
assign bridge_total = (b_q > 32'd9999) ? 16'd9999 : b_q[15:0];
assign s_q = (domains == 16'd0) ? 32'd100
: (({16'd0, one_only_served} * 32'd100) / {16'd0, domains});
assign served_pct = s_q[15:0];
assign one_answer_serves = (domains_unserved == 16'd0) && (domains != 16'd0);
assign truly_unserved = (true_unserved != 16'd0);
assign both_err = evaluate && truly_unserved && one_answer_serves;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
n_evals <= 8'd0; n_unserved <= 8'd0;
end else if (evaluate) begin
n_evals <= n_evals + 8'd1;
if (truly_unserved) n_unserved <= n_unserved + 8'd1;
end
end
endmoduleTwelve domains with five suited to each fabric leaves seven unserved by whichever single answer is forced — forty-one percent served by the better of the two alone, and four hundred and ninety units of bridging for the rest.
| Fact | Value |
|---|---|
| Domains | 12 |
| Suited to the proprietary fabric | 5 |
| Suited to the standard | 5 |
| Served by one answer alone | 5 |
| Unserved | 7 |
| Served | 41% |
The second case is the configuration where forcing one answer is correct. One fabric that genuinely suits every domain serves the whole estate, and the model says so — which is the small system, or the system built around one vendor throughout, and it is a legitimate design.
The fifth case is the state that says the comparison was the wrong one. Neither fabric suits anything means both were evaluated against requirements neither meets, and the answer is a third option rather than a choice between these two.
The last case is the boundary and it is the realistic one. One fabric that nearly covers the estate — eleven domains of twelve — still leaves one, and that one needs either a bridge or the other fabric. Ninety-one percent coverage is not coverage when the remaining domain is a product requirement.
The degenerate case bounds it: an estate with no domains enumerated reports everything served, which is an unwritten estate rather than a covered one.
The reason large systems land on both is that the two connections are genuinely different problems. The link between accelerators in a chassis is short, dense, known at design time, and carries traffic whose pattern the vendor can characterise — everything section 8 says a specialisation can exploit. The link to the host and to memory expansion is longer, crosses a vendor boundary, attaches parts chosen by the buyer, and has to survive the buyer changing its mind. Optimising one fabric for both means being wrong about one of them, and the systems that use both are not being indecisive; they are answering two questions.
The bridging figure in the model is the cost of refusing that. Seventy units per unserved domain is what it costs to reach a domain with the fabric that does not suit it — a converter, a redesign, a compromise on the requirement. It is the same quantity section 6 charges for an unreachable part, one level up: a fabric that does not fit a domain is not a failure, it is a bridge, and the whole of the model is making the bridge appear on the sheet.
The fourth model output is the one to carry away. Serving five domains of twelve with the better single answer is forty-one percent, and using both serves ten of twelve — which is not a hundred either. Two fabrics do not automatically cover an estate, and the two domains left over after both is the residue the design has to handle explicitly. An answer that says "use both" and stops has made the same error as one that says "use the standard" and stops, one step later.
14. RTL 10 — A CXL-Against-Proprietary Comparison Assembled
Nine sections of inputs. This one puts them in one place and makes the confident answer visible as what it is: one bit of six.
// RTL 10 - a CXL-against-proprietary comparison assembled. Nine sections of
// inputs, one summary. "It is an open standard" is bit 0: true, and one sixth
// of an argument.
module comparison_signoff #(parameter int OPEN_IS_THE_ARGUMENT = 0) (
input logic clk, rst_n,
input logic evaluate,
input logic both_named, capability_stated, reach_stated,
input logic lead_stated, lock_stated, ecosystem_stated,
output logic [5:0] fail_mask,
output logic [15:0] conditions_met, sound_pct,
output logic sound,
output logic [7:0] n_evals, n_sound, n_claimed,
output logic signoff_err
);
logic [31:0] s_q;
logic truly_sound, claimed;
assign fail_mask[0] = ~both_named;
assign fail_mask[1] = ~capability_stated;
assign fail_mask[2] = ~reach_stated;
assign fail_mask[3] = ~lead_stated;
assign fail_mask[4] = ~lock_stated;
assign fail_mask[5] = ~ecosystem_stated;
assign conditions_met = {15'd0, both_named} + {15'd0, capability_stated}
+ {15'd0, reach_stated} + {15'd0, lead_stated}
+ {15'd0, lock_stated} + {15'd0, ecosystem_stated};
assign s_q = ({16'd0, conditions_met} * 32'd100) / 32'd6;
// No clamp: conditions_met sums six one-bit values, so the quotient cannot
// exceed a hundred and a ceiling would be unreachable code.
assign sound_pct = s_q[15:0];
assign truly_sound = (fail_mask == 6'd0);
// The openness view reads bit 0 and stops.
assign claimed = (OPEN_IS_THE_ARGUMENT != 0) ? both_named : truly_sound;
assign sound = claimed;
assign signoff_err = evaluate && !truly_sound && claimed;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
n_evals <= 8'd0; n_sound <= 8'd0; n_claimed <= 8'd0;
end else if (evaluate) begin
n_evals <= n_evals + 8'd1;
if (truly_sound) n_sound <= n_sound + 8'd1;
if (claimed) n_claimed <= n_claimed + 8'd1;
end
end
endmoduleThe stimulus walks all six bits one at a time. When both have been named and any one of the other five fails, the assembled model reports that the argument is not sound and the openness view reports an argument.
| Bit | Condition, and the section that builds it |
|---|---|
| 0 | Both were named at all — §14 |
| 1 | A capability argument was made — §5 |
| 2 | The reachable set was counted — §6 |
| 3 | The standardisation lead time was stated — §7 |
| 4 | The exit cost was computed — §11 |
| 5 | The ecosystem was counted in shipping parts — §10 |
Across the eight evaluations, the assembled model calls one argument sound and the openness view calls six of them an argument.
The bit order is by how much of the decision each condition carries. Bit 1 is first among the five because without a capability argument the rest are being applied to a choice nobody has justified. Bits 2 and 5 are the two counts that make openness concrete. Bit 3 is the schedule and bit 4 is the exit, both of which decide programmes rather than architectures.
"It is an open standard" is bit 0, and it is the most socially durable of the three comparison chapters' weak definitions. 28.1's and 28.2's stop early; 28.3's is a category error. This one is a true statement that is also a position, which means it is defended rather than examined — and a claim that gets defended stops being checked.
The five other bits fail independently. A capability argument can be made by somebody who never counted what attaches. The reachable set can be counted with no idea when the standard will be ratified. The lead time can be stated by a programme that has never computed its exit cost. And the ecosystem count is the one most often replaced by the specification count, which is the same substitution the chapter opened with, one level down.
Two of the six bits are not properties of the fabrics at all, and that is the structural point Module 28 has been building towards. Bits 3 and 4 — the lead time and the exit cost — are properties of the programme: when it needs the capability, and how much of its design encodes a fabric's assumptions. Two comparisons of the same two fabrics by two different programmes can correctly reach opposite answers, and neither has made an error. That is why this comparison cannot be settled once and cited afterwards, and why an answer that names no programme has not answered.
Bits 2 and 5 are the two that convert openness from a position into a number, and they fail differently. The reachable set is a count nobody made; the ecosystem is a count made against the wrong list. The first is an omission and the second is a substitution, and the second is harder to catch, because the answer arrives with a number attached and numbers are not usually interrogated for which list they came from.
The three comparison chapters now assemble into one method. 28.1 asks what a protocol does; 28.2 asks where it does it; 28.3 asks at which layer it lives; and this one asks who else can build it, when, and at what cost to leave. A comparison that answers all four is an architecture decision. One that answers the first and stops is a preference with a datasheet attached.
That every failing path lands on one terminal is deliberate rather than a simplification. An argument that skipped one of the five is unsound in exactly the way an argument that skipped all five is, because what it produces is a confident answer — and a confident answer is indistinguishable from a correct one until the thing it did not check turns out to matter. There is no partial credit available here, because the programme does not find out which condition it omitted; it finds out that four parts will not attach, or that ratification is two years out, or that the exit costs fourteen blocks, and by then the decision is made.
The capability argument is first for a reason worth stating separately. The other four conditions are all applied to a choice — they count what attaches to it, when it arrives, what leaving costs, what can be bought for it. If no capability argument was made, there is no choice for them to be applied to, only a preference with counts attached. That is why bit 1 sits directly under the weak definition: it is the first question that can fail in a way the other four cannot repair.
15. Quantitative Reasoning
Four decisions of six with nothing behind them, from an argument of ten claims where eight are about publication — and a quarter supported at twenty decisions.
Five parts of twenty that cannot attach, at two hundred and fifty units of bridging, with six from the vendor and nine implementing the standard.
Six quarters of waiting between a proprietary answer and a ratified standard — seventeen in the case that decides a generation.
Eight cases of twelve given up for three times the rate, and all twelve in the sharpest version.
Five interfaces of eight single-sourced on a design where three are open, because publication without a second implementer is a single source with a document.
Four parts the design needs and cannot buy, from a thirty-part specification with eight shipping — a quarter populated.
Fourteen blocks to rewrite and forty software sites, at eleven hundred and twenty units, on a design thirty percent portable.
Seven hundred units of standard overhead paid by deployments that never exercise it, fourteen of twenty being single-vendor.
Seven domains of twelve unserved by whichever single fabric is forced, at four hundred and ninety units of bridging.
One argument of eight sound; the openness view counts six. The assembled model's summary, and the chapter's.
16. Assertions
The testbenches carry 555 checks across ten models.
Every output of every model is asserted as a value, in both builds. The output listing step reported nothing on either testbench, the seventh chapter running.
Both builds are asserted on every degenerate case. An argument supporting no decision, a design wanting no parts, a comparison with no need date, a comparison with no cases, a design with no interfaces, a specification nobody wrote, a design needing nothing, an uncounted design, a comparison with no deployments, and an estate with no domains.
Every clamp that an input can reach is driven past its limit exactly once. More claims than the argument holds, more parts than the design wants, a bridging cost that saturates, a revenue figure that saturates, a rate ratio that saturates, more open interfaces than the design has, a risk figure that saturates, more parts shipping than specified, a qualification cost that saturates, more portable blocks than exist, an exit cost that saturates, more single-vendor deployments than exist, an overhead that saturates, more domains than the estate has, and a bridging total that saturates.
Every percentage whose numerator is clamped is asserted in an over-claim case chosen so the quotient does not itself saturate, which is section 17's finding and is a refinement of the rule this batch inherited.
Every error output is checked in both directions in every case. Section 5's second, third, fourth and sixth cases, section 6's second, third and fourth, section 7's second and fifth, section 8's second and sixth, section 9's second, third and fourth, section 10's second, third and sixth, section 11's second and third, section 12's second and fifth, and section 13's second, third and fourth exist to assert the quiet half. Each is a case where the openness view is right, and a model that alarmed on them would be unusable.
17. Mutation Testing
119 mutations, 119 killed. Fifty-eight against the first testbench, sixty-one against the second. The first run killed a hundred and eighteen and left one — and that one refined a rule this batch inherited.
| Mutation family | Count, and what it breaks |
|---|---|
| Clamp inverted or removed | 24 — a bounded count reports the raw value, or wraps |
| Parameter-selected branches swapped | 21 — each build computes the other one's answer |
| Guard or zero-case result flipped | 13 — a degenerate input reports a confident answer |
| Boundary loosened or tightened | 3 — an equality lands on the wrong side |
| Conjunction turned into a disjunction | 9 — a two-part condition becomes a one-part one |
| Arithmetic reversed or wrong operator | 23 — a difference underflows, a product becomes a sum |
| Mask bit inverted | 6 — one condition reports the opposite of itself |
| Counter inverted or double-stepped | 20 — a decision is corrupted with no output changing |
The single survivor sharpened the percentage rule. Batch 028 established that a percentage with a clamped numerator must be asserted in the case that over-claims. Section 5's over-claim case existed and asserted the percentage — and the mutation survived anyway, because the over-claim was large enough that the percentage clamp fired in both builds. Twenty capability claims against ten that exist, over six decisions, gives a hundred and sixty-six percent unmutated and three hundred and thirty-three mutated, and both saturate at a hundred.
The rule therefore needs a clause: the over-claim case has to be chosen so that the quotient stays inside the clamp. Raising the denominator from six decisions to twenty does it — fifty percent against a hundred, and the mutation dies. An assertion in a saturating case tests the clamp and not the numerator, which is the same masking relationship this batch has now found in three separate forms: a clamp behind a minimum, a clamp behind an outer clamp, and now a clamp behind itself.
Nothing else survived, which is the first chapter in the batch where every other rule held on its first application — including two models whose unused inputs were caught by reading rather than by a campaign, and one whose "true" quantity was parameter-dependent and would have made its own error output structurally undetectable.
18. Verification Strategy
Separate the openness claims from the capability claims and count both. Section 5. A claim that no measurement could contradict cannot distinguish two options.
Count the parts that can actually attach. Section 6. That is what openness buys, and it is a number.
Put both dates on the table. Section 7. Standardisation has a lead time and a programme either has it or does not.
Ask what the specialisation gave up. Section 8. The gain is usually real; the trade is usually unstated.
Count suppliers per interface, not published specifications. Section 9. One implementer is a single source with a document.
Count shipping parts, not specified ones. Section 10.
Compute the exit cost in blocks and in call sites. Section 11. Both columns, and the second is the one that goes missing.
Name the deployment where the proprietary fabric is the right answer. Section 12. An analysis that cannot is an advertisement.
Check whether the estate needs both. Section 13. Most large ones do.
19. Synthesis and Implementation Reality
A proprietary fabric's specification detail varies and its evolution is the vendor's to schedule, which is simultaneously its advantage in section 7 and its exposure in section 11.
CXL's consortium model is what produces both the lead time and the ecosystem. The same process that makes ratification slow is what makes several vendors implement the result, and treating either half as separable from the other misunderstands the mechanism.
Bridges between an open fabric and a proprietary one exist and are real products, with the same approximation problem 28.2 section 13 describes — message kinds without an equivalent have to be handled conservatively.
A device can support both, at the cost of two link stacks and the silicon for each, which is 28.3 section 13's arithmetic applied to a commercial choice rather than a geometric one.
And the answer changes over time in one direction more often than the other. Ecosystems grow, so a standard that was thin at design time may not be at the next generation — which is an argument for computing section 11's exit cost early rather than for waiting.
The practical form of that argument is worth stating plainly, because it is what a programme should actually do. If the capability is needed before the standard exists, use the proprietary fabric and compute the exit cost at the same time — not later, when the estimate is needed under pressure. The exit cost computed at design time is cheap, because the person computing it is the person who knows which blocks encode which assumptions. The same number computed three years later is an archaeology project.
The corollary is an argument for an abstraction layer that is narrower than it sounds. A programme that has computed an exit cost of fourteen blocks can decide whether an abstraction layer is worth its price. A programme that has not computed one either builds the layer on principle — paying for an option it may not need — or skips it on principle, which is the same decision made without the number. Section 11's whole purpose is to put that choice on a sheet.
One more reality is worth recording because it cuts against the chapter's own tidiness. The counts in sections 6, 9 and 10 are all obtainable, and they are obtainable by somebody — usually procurement — who is not in the room when the fabric decision is made. The most common reason this method is not applied is not disagreement with it; it is that the architecture decision and the parts data live in different organisations. The fix is a meeting, not a model, and an engineer who can say precisely which four counts they need has a better chance of getting that meeting than one who asks for "the procurement view".
20. Silicon Observability
Free, and from a bill of materials. Which parts the design wants and who supplies each. Sections 6 and 9.
Free, and from a specification list against a product catalogue. Specified parts against shipping parts. Section 10.
Cheap, and from a roadmap. The two dates in section 7 — though the ratified date is an estimate and should be recorded as one.
Moderate. The block-level portability split. Section 11's first column requires somebody to go through the design and say which blocks encode fabric-specific assumptions.
Moderate, and owned by another team. The software call-site count. Section 11's second column, and the reason the estimate is usually low.
Expensive. Measured rate on both fabrics for the same workload. Section 8's gain is the number most often quoted from a datasheet and least often measured in place.
Expensive, and rarely attempted. The cases a point solution does not handle. Section 8's other half is a specification comparison rather than a benchmark, and almost nobody does it.
21. Debug Lab
A programme is deadlocked on a fabric decision.
Step 1 — separate the claims. Section 5. If most of the argument is about openness or about vendor preference, the technical case has not been made by either side.
Step 2 — count the parts that attach under each option. Section 6. This is usually decisive and it takes an afternoon.
Step 3 — put both dates on the table. Section 7. A ratification date beyond the product's window ends the argument.
Step 4 — count shipping parts, not specified ones. Section 10.
Step 5 — compute the exit cost under each option. Section 11. Both columns. This converts the lock-in anxiety into a number that can be compared.
Step 6 — ask whether the estate needs both. Section 13. The deadlock is frequently caused by forcing one answer onto domains with different requirements.
Steps 1 to 4 are counts from documents the programme already has, and in practice the decision is usually made by step 3.
22. Design Review
Which claims in this argument are about capability, and which are about the specification being published?
How many of the parts this design wants can attach under each option?
When is the capability needed, when could each option deliver it, and what is the gap?
What does the specialisation give up, and does this design need any of it?
How many suppliers implement each interface — not how many could?
How many parts are shipping, as against specified?
What is the exit cost in blocks, and what is it in software call sites?
Which deployment in this estate is the proprietary fabric's best case?
Does the estate have domains that want different answers?
23. How This Appears In Real Engineering
The decision is made on identity rather than on counts, and it goes wrong in both directions.
The most common shape is section 5 in the open direction. A programme standardises because standardising is the right thing to do, discovers at integration that four of the parts it needs have no CXL implementation, and spends the schedule it saved on bridges. The principle was sound and the count was never made.
The second is section 5 with the opposite sign. A programme picks the vendor fabric because the vendor's parts are what it is buying, which is correct, and never computes section 11's exit cost — so when the next generation wants a second accelerator source there is no estimate for what that would take, and the decision gets made again under time pressure.
The third is section 7 and it is the one that is nobody's fault. The capability is needed before the standard exists. The programme uses the proprietary fabric because it must, ships, and is then described internally as having "chosen proprietary" — when what happened was that it chose a date.
The fourth is section 10. A specification is read as a catalogue. The parts list is built from the standard's device categories, procurement discovers how many are actually shipping, and the design is re-cut around what can be bought.
The fifth is section 13 and it is the most expensive of the five. A programme forces one answer onto an estate with two kinds of connection, because a single fabric was treated as an architectural virtue. The accelerator-to-accelerator links get a fabric optimised for a host connection or the host connection gets one optimised for short dense links, and the compromise shows up as a performance shortfall that nobody can attribute — because the fabric is meeting its specification everywhere and simply meeting the wrong one in half the estate.
The sixth is section 12 in reverse and it is the one that damages credibility. An architect presents an open-standard recommendation that cannot name the case where the proprietary fabric wins, an experienced reviewer who has deployed a single-vendor estate names it in the meeting, and the whole analysis loses standing — including the four counts in it that were correct. The reverse case is not a courtesy to the other side; it is what makes the rest of the argument survive review.
The pattern is that this comparison's inputs are all counts and its usual arguments are all positions, and the whole of the method is replacing the second with the first.
And there is a reason positions win by default that is not anybody's failing. The counts require data from procurement, from a software team and from a roadmap that may be under embargo, while a position requires none — so the position is available at the moment the decision is being made and the counts are available two weeks later. The method's real cost is the two weeks, and the argument for paying it is every one of the six failure shapes above, each of which cost more than two weeks to discover.
24. Common Misconceptions
"It is an open standard." True, and one condition of six. Section 14.
"Open means anything can attach." It means anything that implemented it can. Count them. Section 6.
"Standardising costs nothing." It costs the ratification gap. Section 7.
"Proprietary is just lock-in." It is also specialisation, and the specialisation is usually real. Section 8.
"Published means second-sourced." Only if somebody else implemented it. Section 9.
"The standard supports thirty device types." How many are shipping? Section 10.
"We could move later if we had to." Fourteen blocks and forty call sites later. Section 11.
"Open is always the right choice." Name the deployment where it is not. Section 12.
"We have to pick one." Most large systems use both. Section 13.
25. Interview Reasoning
"Why would you use CXL rather than a vendor's own coherent fabric?" The honest answer is a set of counts rather than a principle. How many of the parts this design needs can attach under each option — that is what openness actually buys. How many suppliers implement each interface, because publication without a second implementer is a single source with a document. How many parts are shipping rather than specified. And what it would cost to leave, in blocks and in software call sites.
"And why would you use the proprietary one?" Because the capability is needed before the standard will exist, or because the specialisation buys something this workload needs, or because the deployment is single-vendor anyway and the standard's generality returns nothing. All three are real and the first is the most common.
"Is the proprietary fabric faster?" Sometimes, and the useful question is what it gave up to be. A point solution can assume the topology, the clocking and the software stack, and every assumption removes a case. If this design needs none of those cases, the gain is free; if it needs them, it is not.
"How do you price lock-in?" As an exit cost. Count the blocks that encode fabric-specific assumptions and the software call sites written against its semantics. That turns an anxiety into a budget line, and it is knowable at design time rather than at the point of leaving.
"Your standard supports thirty device categories." How many are shipping? A specification is a roadmap until parts exist, and a design can only buy what exists. That interval is normal and it has to be planned against rather than argued with.
"Give me the shortest honest answer." Openness is one condition of six. The other five are a capability argument, the count of parts that can actually attach, the standardisation lead time, the exit cost in blocks and call sites, and the ecosystem counted in shipping parts. Two of those six are properties of the programme rather than of either fabric, which is why two teams can compare the same two fabrics and correctly disagree.
"What is the single most common mistake?" Reading a specification as a catalogue. A standard describing thirty device categories with eight shipping supports a design that needs eight of them, and the interval between publication and supply is normal, invisible in any openness argument, and has to be planned against rather than argued with.
"Do you have to choose?" Usually not. A large system commonly runs the vendor's fabric between its accelerators and an open standard to the host and memory, because those connections have different reachable sets and different exit considerations. Forcing one answer means discarding one of those domains.
26. Exercises
1. An argument has 16 claims, 11 about openness, supporting 9 decisions. Compute the unbacked count and the supported fraction. How many capability claims would be needed to reach 100%?
2. A design wants 35 parts; 9 come from the vendor and 14 implement the standard. Compute the reachable set and the bridging at 80 units each. What happens to the count if two more vendors implement the standard?
3. A capability is needed in Q2. A proprietary answer lands in Q3 and a ratified standard in Q14. Compute both gaps and the wait. At what revenue rate does the wait cost more than a full redesign at 6,000 units?
4. A point solution runs at 320 against a standard's 96, handling 5 of 18 cases. Compute the gain, the ratio and the cases given up. Which five cases would you want named?
5. A design has 11 interfaces, 4 of them open, one supplier each, at 200 units of risk. Compute the single-sourced count and the risk. What changes if a second supplier appears for the open four?
6. A standard specifies 45 device types; 11 ship and the design needs 18. Compute the missing count and the populated fraction. How many periods at 3 new parts each until the design is buildable?
7. 30 blocks with 9 portable at 120 units, plus 65 software call sites. Compute the hardware exit. What would you need to know to cost the second column?
8. 40 deployments, 31 single-vendor, 90 units of overhead against 25 of realised gain. Compute the net overhead paid for nothing. At what gain does it reach zero?
9. 20 domains, 9 suited to the proprietary fabric and 8 to the standard. Compute what one answer serves and what it leaves. What does using both serve?
10. Extend the assembled model with a seventh bit for a condition this chapter does not cover. Justify its position using the rule that the ordering is by how much of the decision each condition carries.
27. Summary
Openness is a property of the specification, and a claim no measurement could contradict cannot distinguish two options.
The reachable set is what openness buys, and it is a count — five parts of twenty out of reach is a procurement fact, not a principle.
A standard has a lead time, and six quarters is longer than some products live.
A point solution can specialise, and the gain is usually real — eight cases of twelve is what it cost.
Second-sourcing is a count of suppliers, not of published specifications.
The ecosystem is the shipping parts, not the specified ones, and a standard with all of the openness and none of the parts is a normal early state.
The exit cost is knowable in advance, in blocks and in software call sites — and the second column is the one that goes missing.
Proprietary wins where the generality returns nothing, and an analysis that cannot name that deployment is an advertisement.
Most large systems use both, and forcing one answer discards a domain.
Six bits, and "it is an open standard" is one of them. One argument of eight is sound; the openness view counts six.
Continue learning
Related tutorials
- Related topic
Device-Type Question
The type is an answer, not a question. This chapter builds workload characterisation, the cache question, the memory question, the cost of the wrong type, Type 2's price, procurability, phase variation, the cost of finding out late and the order the questions are asked in.
- Related topic
CXL vs PCIe
The two share a stack and differ in what the stack decides. This chapter builds the shared-layer count, access granularity, who initiates, the latency tier, the ordering model, failure semantics, the software model, when PCIe wins and what a migration costs.
- Related topic
CXL vs CHI
Both are coherency protocols and they stop in different places. This chapter builds the domain's scope, symmetry, home placement, the transport, the failure boundary, how each scales, the state mapping, where each wins and what a bridge costs.
- Related topic
CXL vs UCIe
The question is usually malformed: one is a transport and the other is a protocol. This chapter builds the layer separation, reach against density, energy per bit, what UCIe carries, the substrate profile, the latency tier, the yield problem, where each applies and what two stacks cost.
Standards & specifications
- Governing standard
- CXL Specification (CXL Consortium)(opens CXL Consortium in a new tab)
Defines CXL.io, CXL.cache and CXL.mem, and the coherence and memory-pooling behaviour built on them. System design and deployment topology are not mandated.
This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.
Where this fits
Part of the CXL curriculum.
