CXL · Module 25
CXL VIP Usage
A commercial VIP moves every question in this module inside a component you cannot read. This chapter builds configuration surface, revision gaps, rule overlap, correlated readings, licence bounds, injection reach, debug opacity, version churn, buy-against-build and the assembled sign-off.
Module 25 has asked five questions: whether a rule was checked, whether the check was wide enough, when it sampled, how it matched, and what the coverage number measured. A commercial VIP answers all five inside a component you did not write and cannot read — and the answer arrives as "no errors reported."
That is not a criticism of VIPs. A VIP is the right decision most of the time: section 13's arithmetic is ninety days against two hundred and forty. It is a criticism of reading the report as if it were an answer to your question rather than to the vendor's.
1. The Engineering Problem — Somebody Else's Answers To Your Questions
A VIP's configuration surface is large and its defaults are decisions. Two hundred options with sixty read is a hundred and forty nobody looked at, and four of them turn a check off. Section 5.
A VIP is built against a revision of the specification. A DUT at revision 3 against a VIP at revision 2 is eighteen rules unchecked and six checked by the old wording — twenty-four rules of exposure. Section 6.
A vendor's rule list and the specification's rule list are different lists. Three hundred VIP rules plus eighty of your own against four hundred in the specification is sixty rules with no checker at all. Section 7.
A VIP built from the same reading of an ambiguous clause agrees with your DUT and with nothing else. Twelve of twenty ambiguous clauses read the same way is sixty percent of the ambiguity invisible to both. Section 8.
And the licences bound the regression, not the machines. Four hundred machines with forty licences is five hundred minutes of wall clock against a plan of fifty. Section 9.
This chapter against the rest of Module 25, stated precisely. Those four own properties of checks you wrote. This one owns the same properties when you did not write them — which is why every model here is about what you can establish from outside, and why section 14's weak definition is a VIP reporting no errors.
2. The One-Sentence Model
A VIP-based environment is trustworthy when every option has been read, the VIP and the DUT target the same revision, specification rules outside the VIP are checked by you, the VIP is not the DUT's own reading of an ambiguous clause, and every error case can actually be injected — and "the VIP reports no errors" is none of those five.
3. What This Chapter Owns
| Ground | Owner |
|---|---|
| Whether a rule was checked at all | 25.1 |
| Whether a check was wide enough | 25.2 |
| When a check samples and who is told | 25.3 |
| Pairing a response to its request | 25.4 |
| What the coverage percentage measures | 25.5 |
| All five, when the component is somebody else's | this chapter |
Deferred:
| Deferred ground | Owner |
|---|---|
| Rule coverage and checker strength | 25.1 §5 · §9 |
| Invariant scope and snoop-filter recall | 25.2 §5 · §7 |
| Vacuity, gating and severity | 25.3 §6 · §7 · §12 |
| Bin partitioning and closure curves | 25.5 §5 · §11 |
| Cryptographic primitives | out of scope — see §4 |
4. Teaching-Model Boundary
Every model is a small synchronous block that computes one thing you can establish about a component from outside it. A real VIP is a compiled or encrypted library with an agent, a monitor, checkers, a coverage model and a configuration API, and none of that is reproduced. What is reproduced is the arithmetic of integrating one, and the shape of the mistake when the report is read as an answer.
Three simplifications are worth stating. Section 6 treats a revision gap as a single count of affected rules, where the real mapping is clause by clause. Section 8 treats a clause as read the same way or not, where real ambiguity is a spectrum. Section 12 prices vendor turnaround as a flat per-escalation figure. In each case the conclusion is the same and the model is abbreviated.
Each model is built twice — a correct build and a broken build selected by a parameter. Every broken build here is what buying a VIP is supposed to buy you: trust the defaults, assume the revisions match, assume the VIP checks the protocol, treat it as an independent reference, count the machines, assume it can inject anything, read the source, upgrade for free, pay only the licence. Each is the reason the VIP was bought, which is exactly why each goes unexamined.
Figure 1 — The report on the left is accurate. Everything in the middle column is between it and any statement about the design, and none of it is visible from inside the component that produced the report.
5. RTL 1 — Every Default Is A Decision Somebody Else Made
// RTL 1 - the configuration surface. A VIP ships with options, and an option
// left at its default can disable a check without ever saying so.
module vip_config #(parameter int TRUST_DEFAULTS = 0) (
input logic clk, rst_n,
input logic audit,
input logic [15:0] total_options, checked_options, disabling_defaults,
output logic [15:0] reviewed, unreviewed, checks_off, reviewed_pct,
output logic config_understood,
output logic [7:0] n_audits, n_blind,
output logic defaults_trusted_err
);
logic [31:0] p_q;
assign reviewed = (TRUST_DEFAULTS != 0) ? 16'd0
: ((checked_options > total_options) ? total_options
: checked_options);
assign unreviewed = (total_options > reviewed) ? (total_options - reviewed) : 16'd0;
// A default that turns a check off is off until somebody reads it.
assign checks_off = (disabling_defaults > unreviewed) ? unreviewed
: disabling_defaults;
assign p_q = (total_options == 16'd0) ? 32'd100
: (({16'd0, reviewed} * 32'd100) / {16'd0, total_options});
assign reviewed_pct = (p_q > 32'd100) ? 16'd100 : p_q[15:0];
assign config_understood = (unreviewed == 16'd0);
// Options nobody read, at least one of which turns a check off.
assign defaults_trusted_err = audit && (checks_off != 16'd0);
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
n_audits <= 8'd0; n_blind <= 8'd0;
end else if (audit) begin
n_audits <= n_audits + 8'd1;
if (!config_understood) n_blind <= n_blind + 8'd1;
end
end
endmoduleSix audits. Two hundred options, four of which disable a check.
| Options reviewed | Reviewed · Unreviewed · Checks off |
|---|---|
| 60 | 60 · 140 · 4 silently off · 30% — trusting the defaults reviews 0 |
| 200 | 200 · 0 · 0 · understood · the default-trusting model still leaves four off |
| 250 — more than exist | 200, clamped · 0 · 0 |
| 60, no disabling defaults | 60 · 140 · 0 off — still not understood, but nothing is disabled |
| 198 | 198 · 2 · 2 off — at most the unreviewed count |
| a VIP with no options | 0 · 0 · 0 · 100% · understood |
Three blind when the options are reviewed; five when the defaults are trusted.
A VIP's configuration is its behaviour, and the defaults were chosen to make it start. They are chosen for the widest possible customer base, which means permissive: unknown message types tolerated, optional rules relaxed, a strictness level set low enough that a partially-built DUT connects. Every one of those is a check that is off.
Row one is the arithmetic of the exposure. A hundred and forty options nobody read, four of which disable something. The four are not marked — no report says "check X is disabled" — and finding them means reading the configuration reference against your own rule list.
Row four separates the two failures. A hundred and forty unreviewed options with none of them disabling is still an unreviewed configuration, and the model reports it as not understood while raising no error. Not knowing is not the same as being wrong, and only one of the two is a defect.
6. RTL 2 — A VIP Checks The Revision It Was Built Against
// RTL 2 - specification revision. A VIP built against one revision of the
// specification checks that revision's rules, whatever the DUT implements.
module revision_gap #(parameter int ASSUME_SAME_REV = 0) (
input logic clk, rst_n,
input logic compare_it,
input logic [15:0] dut_rev, vip_rev, rules_added, rules_changed,
output logic [15:0] gap_revs, unchecked_rules, wrongly_checked, exposure,
output logic revisions_aligned,
output logic [7:0] n_compares, n_misaligned,
output logic revision_ignored_err
);
assign gap_revs = (dut_rev > vip_rev) ? (dut_rev - vip_rev) : 16'd0;
// Rules the DUT gained are unchecked; rules that changed are checked wrong.
assign unchecked_rules = (ASSUME_SAME_REV != 0) ? 16'd0
: ((gap_revs != 16'd0) ? rules_added : 16'd0);
assign wrongly_checked = (ASSUME_SAME_REV != 0) ? 16'd0
: ((gap_revs != 16'd0) ? rules_changed : 16'd0);
assign exposure = unchecked_rules + wrongly_checked;
assign revisions_aligned = (gap_revs == 16'd0);
// A revision gap with rules behind it, reported as none.
assign revision_ignored_err = compare_it && (gap_revs != 16'd0)
&& ((rules_added != 16'd0) || (rules_changed != 16'd0))
&& (exposure == 16'd0);
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
n_compares <= 8'd0; n_misaligned <= 8'd0;
end else if (compare_it) begin
n_compares <= n_compares + 8'd1;
if (!revisions_aligned) n_misaligned <= n_misaligned + 8'd1;
end
end
endmoduleFive comparisons. Eighteen rules added and six changed between revisions.
| DUT rev / VIP rev | Gap · Unchecked · Wrongly checked |
|---|---|
| 3 / 2 | 1 · 18 · 6 · 24 rules of exposure — the same-revision model reports 0 |
| 3 / 3 | 0 · 0 · 0 · aligned |
| 3 / 4 — the VIP is ahead | 0, floored · reads as aligned |
| 3 / 2, no rules changed between them | 1 · 0 · 0 · a version number, not an exposure |
| 5 / 2 | 3 · 18 · 6 · the same twenty-four |
Three misaligned — the same three either way, because a revision number is a fact regardless of the model.
A VIP's rule set is frozen at its build, and a specification revision moves two things. Rules that were added have no checker at all; rules that changed have a checker that enforces the previous wording — and the second kind is worse, because it produces confident failures against a correct design and confident passes against an incorrect one.
Row four is the distinction the audit has to make. A revision gap with nothing behind it is a version number. The exposure is not the gap; it is the rules inside the gap, and the number that matters comes from the specification's change list rather than from the two version strings.
Row three is the direction that is usually safe and occasionally not. A VIP ahead of the DUT enforces rules the DUT is not required to obey — failures against a compliant design, which cost triage time but do not hide bugs. The model floors the gap at zero rather than wrapping, and reports it as aligned.
7. RTL 3 — The Vendor's Rule List Is Not The Specification's
// RTL 3 - what the VIP actually checks. A vendor's rule list and the
// specification's rule list are different lists, and only one is published.
module rule_overlap #(parameter int VIP_CHECKS_EVERYTHING = 0) (
input logic clk, rst_n,
input logic audit,
input logic [15:0] spec_rules, vip_rules, own_rules, overlap,
output logic [15:0] covered, gap, duplicated, covered_pct,
output logic rules_covered,
output logic [7:0] n_audits, n_gapped,
output logic vip_assumed_complete_err
);
logic [31:0] c_q, p_q;
// The VIP's rules plus your own, minus what both check.
assign c_q = (VIP_CHECKS_EVERYTHING != 0) ? {16'd0, spec_rules}
: ({16'd0, vip_rules} + {16'd0, own_rules} - {16'd0, overlap});
assign covered = (c_q > {16'd0, spec_rules}) ? spec_rules
: ((c_q > 32'd65535) ? 16'hFFFF : c_q[15:0]);
assign gap = (spec_rules > covered) ? (spec_rules - covered) : 16'd0;
assign duplicated = overlap;
assign p_q = (spec_rules == 16'd0) ? 32'd100
: (({16'd0, covered} * 32'd100) / {16'd0, spec_rules});
assign covered_pct = (p_q > 32'd100) ? 16'd100 : p_q[15:0];
assign rules_covered = (gap == 16'd0);
// Specification rules nobody checks, on a VIP assumed to check them all.
assign vip_assumed_complete_err = audit
&& (spec_rules > (vip_rules + own_rules - overlap))
&& rules_covered;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
n_audits <= 8'd0; n_gapped <= 8'd0;
end else if (audit) begin
n_audits <= n_audits + 8'd1;
if (!rules_covered) n_gapped <= n_gapped + 8'd1;
end
end
endmoduleSeven audits. Four hundred specification rules, a VIP checking three hundred.
| Your rules / overlap | Covered · Gap · Duplicated |
|---|---|
| 80 / 40 | 340 · 60 with no checker · 40 checked twice · 85% |
| 140 / 40 | 400 · 0 · covered |
| 140 / 40 | exactly 400 · 0 · nothing to spare |
| 139 / 40 | 399 · 1 rule with no checker |
| 100 / 0 overlap | 400 · 0 · 0 duplicated — the efficient case |
| 200 / 40 | 400, clamped · 0 · over-checking is not a gap |
| an empty specification | 0 · 0 · 100% · not a complete VIP, an empty list |
Two audits with a gap; none when the VIP is assumed complete.
"The VIP checks the protocol" is a sentence with no quantity in it. A vendor implements the rules its customers ask for, in the order they ask, and the intersection with the specification's full rule set is a number the vendor rarely publishes and the customer rarely computes. Three hundred of four hundred is a good VIP; the other hundred is your work.
Row one is what the audit produces. Sixty rules with no checker anywhere, and forty checked twice — the duplication is harmless and the sixty are the deliverable. Producing this table means listing the specification's rules and ticking each against the VIP's documentation, which is a week and is the only way to get the number.
Row seven is worth stating because it is the arithmetic's edge. An empty specification reports a hundred percent covered, which is consistent and empty. A coverage-style percentage over a rule list is only meaningful alongside the list's length — the same finding as 25.5 §7, arriving from the rule side rather than the bin side.
8. RTL 4 — A VIP Built From The Same Reading Agrees With Your DUT
// RTL 4 - the VIP as reference model. A VIP and a DUT built from the same
// reading of an ambiguous clause agree with each other and with nothing else.
module common_reading #(parameter int VIP_IS_TRUTH = 0) (
input logic clk, rst_n,
input logic judge,
input logic [15:0] ambiguous_clauses, same_reading, independent_reading,
output logic [15:0] agreed_wrongly, caught, would_catch, blind_pct,
output logic independent_check,
output logic [7:0] n_judgements, n_correlated,
output logic correlation_ignored_err
);
logic [31:0] p_q;
// Where both read the clause the same way, a disagreement cannot arise.
assign agreed_wrongly = (same_reading > ambiguous_clauses) ? ambiguous_clauses
: same_reading;
assign would_catch = (ambiguous_clauses > agreed_wrongly)
? (ambiguous_clauses - agreed_wrongly) : 16'd0;
assign caught = (VIP_IS_TRUTH != 0) ? ambiguous_clauses : would_catch;
assign p_q = (ambiguous_clauses == 16'd0) ? 32'd0
: (({16'd0, agreed_wrongly} * 32'd100) / {16'd0, ambiguous_clauses});
assign blind_pct = (p_q > 32'd100) ? 16'd100 : p_q[15:0];
assign independent_check = (independent_reading != 16'd0)
&& (agreed_wrongly == 16'd0);
// Clauses both sides read the same way, reported as checked.
assign correlation_ignored_err = judge && (agreed_wrongly != 16'd0)
&& (caught == ambiguous_clauses);
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
n_judgements <= 8'd0; n_correlated <= 8'd0;
end else if (judge) begin
n_judgements <= n_judgements + 8'd1;
if (!independent_check) n_correlated <= n_correlated + 8'd1;
end
end
endmoduleSix judgements. Twenty ambiguous clauses.
| Read the same way / independent reading | Agreed · Could be caught · Blind |
|---|---|
| 12 / 8 | 12 · 8 · 60% invisible — the VIP-is-truth model claims all 20 |
| 0 / 8 | 0 · 20 · 0% · independent |
| 20 / 8 | 20 · 0 · 100% blind |
| 30 — more than exist | 20, clamped · 0 · nothing left to catch |
| no ambiguity at all | 0 · 0 · reads as independent |
| 0 / no independent reading | 0 · 20 · not independent — there is no second opinion |
Four correlated — the same four either way, because a shared reading is a fact regardless of the model.
A VIP is only a reference model where it disagrees with you for a reason. Where the specification is ambiguous and the vendor's engineer and your designer read the clause the same way — which is likely, because they read the same words — the VIP and the DUT agree, and the agreement is evidence of nothing.
Row three is the reduction. Every clause read the same way makes the VIP a mirror: it will never fire on an ambiguity, and a hundred percent of the interpretation risk is invisible. That is the case where a second independent reading is the entire value, and buying a VIP has not provided one.
Row six is the distinction that keeps the check honest. No shared reading and no independent reading either — nobody has read the clauses twice, and the model reports not-independent rather than independent. Zero agreement is not evidence of independence when there was only ever one opinion.
9. RTL 5 — The Licences Bound The Regression, Not The Machines
// RTL 5 - licences. A regression's parallelism is bounded by the licences
// available, not by the machines, and the queue is the difference.
module licence_bound #(parameter int MACHINES_ARE_THE_LIMIT = 0) (
input logic clk, rst_n,
input logic plan_it,
input logic [15:0] machines, licences, jobs, minutes_each,
output logic [15:0] parallel, waves, wall_min, idle_machines,
output logic plan_realistic,
output logic [7:0] n_plans, n_queued,
output logic licence_ignored_err
);
logic [31:0] w_q, m_q;
// The number that runs at once is the smaller of the two.
assign parallel = (MACHINES_ARE_THE_LIMIT != 0) ? machines
: ((machines > licences) ? licences : machines);
assign w_q = (parallel == 16'd0) ? 32'd0
: (({16'd0, jobs} + {16'd0, parallel} - 32'd1) / {16'd0, parallel});
assign waves = (w_q > 32'd65535) ? 16'hFFFF : w_q[15:0];
assign m_q = {16'd0, waves} * {16'd0, minutes_each};
assign wall_min = (m_q > 32'd65535) ? 16'hFFFF : m_q[15:0];
assign idle_machines = (machines > parallel) ? (machines - parallel) : 16'd0;
assign plan_realistic = (parallel <= licences);
// Machines counted as parallelism when the licences are the bound. No guard
// on machines is needed: parallel is clamped to licences in the correct
// build, so it exceeds them only when machines do, in the broken one.
assign licence_ignored_err = plan_it && (parallel > licences);
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
n_plans <= 8'd0; n_queued <= 8'd0;
end else if (plan_it) begin
n_plans <= n_plans + 8'd1;
if (idle_machines != 16'd0) n_queued <= n_queued + 8'd1;
end
end
endmoduleSix plans. Four hundred machines, two thousand jobs of ten minutes.
| Licences | Parallel · Waves · Wall clock · Idle |
|---|---|
| 40 | 40 · 50 waves · 500 min · 360 idle — the machine model plans 50 min |
| 400 | 400 · 5 · 50 · 0 idle |
| 399 | 399 · 6 waves · one idle machine costs a whole wave |
| 40, 2,000 jobs | 40 · exactly 50 waves, no remainder |
| 40, 2,001 jobs | 40 · 51 waves · 510 min for one extra job |
| 0 licences | 0 · 0 · 0 · nothing runs |
Five plans with machines idle; none when the machines are the limit.
A regression plan is a division, and the divisor is the licence count. Forty licences against two thousand jobs is fifty waves however many machines are available — a factor of ten between the plan and the reality, and the machines that cannot run are the visible symptom.
Rows four and five are the ceiling, and it is coarse. Two thousand jobs at forty parallel is exactly fifty waves; two thousand and one is fifty-one, which is ten more minutes for one more job. Wave granularity means a regression's wall clock moves in steps of minutes_each, and a plan quoted to the minute is wrong between the steps.
Row three is the same effect at the other end. One licence short of the machine count costs a whole extra wave — five to six, a twenty percent increase in wall clock for one licence. The licence count is not a smooth cost curve, and the right number to buy is usually the one that removes a wave.
10. RTL 6 — A VIP Injects The Errors Its Vendor Implemented
// RTL 6 - error injection. A VIP injects the errors its vendor implemented,
// and the ones it cannot inject are the ones nobody tests.
module injection_reach #(parameter int VIP_INJECTS_ALL = 0) (
input logic clk, rst_n,
input logic audit,
input logic [15:0] error_cases, vip_injectable, hand_injectable, overlap,
output logic [15:0] reachable, unreachable, hand_effort_days, reach_pct,
output logic every_case_reachable,
output logic [7:0] n_audits, n_short,
output logic injection_assumed_err
);
logic [31:0] r_q, p_q;
assign r_q = (VIP_INJECTS_ALL != 0) ? {16'd0, error_cases}
: ({16'd0, vip_injectable} + {16'd0, hand_injectable}
- {16'd0, overlap});
assign reachable = (r_q > {16'd0, error_cases}) ? error_cases
: ((r_q > 32'd65535) ? 16'hFFFF : r_q[15:0]);
assign unreachable = (error_cases > reachable) ? (error_cases - reachable) : 16'd0;
// Everything the VIP cannot inject is built by hand, at three days each.
assign hand_effort_days = hand_injectable * 16'd3;
assign p_q = (error_cases == 16'd0) ? 32'd100
: (({16'd0, reachable} * 32'd100) / {16'd0, error_cases});
assign reach_pct = (p_q > 32'd100) ? 16'd100 : p_q[15:0];
assign every_case_reachable = (unreachable == 16'd0);
// Error cases nothing can produce, on a VIP assumed to inject them all.
assign injection_assumed_err = audit
&& (error_cases > (vip_injectable + hand_injectable
- overlap))
&& every_case_reachable;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
n_audits <= 8'd0; n_short <= 8'd0;
end else if (audit) begin
n_audits <= n_audits + 8'd1;
if (!every_case_reachable) n_short <= n_short + 8'd1;
end
end
endmoduleSix audits. Sixty error cases, a VIP injecting forty.
| Hand-injectable / overlap | Reachable · Unreachable · Hand effort |
|---|---|
| 12 / 4 | 48 · 12 nothing can produce · 36 days · 80% |
| 24 / 4 | 60 · 0 · 72 days of hand work |
| 24 / 4 | exactly 60 · 0 · nothing to spare |
| 23 / 4 | 59 · 1 case · which is enough to fail |
| the VIP injects all sixty | 60 · 0 · 0 days — the case the assumption is right about |
| 30 / 4 | 60, clamped · 0 · spare capability is not a shortfall |
Two audits short of full reach; none when the VIP is assumed to inject everything.
Error injection is the capability with the widest spread between vendors and the least visibility. A VIP injects the malformed packets, CRC errors and protocol violations its vendor implemented — a list that grows with customer requests — and the cases outside it need a hand-built stimulus that reaches inside the interface.
Row one is the arithmetic of the plan. Twelve cases nothing can produce, and thirty-six days to build the twelve that can be hand-injected. The eighty percent reach is the number to negotiate the VIP on; the thirty-six days is the number that belongs in the schedule and usually is not there.
Row five is the case that justifies the purchase. A VIP that injects every case costs no hand work at all — which is the outcome the assumption describes, and it does happen. The error fires only when there are cases nothing can reach, not merely when the VIP is short.
11. RTL 7 — Debug Stops At A Boundary You Cannot Read
// RTL 7 - debug through an encrypted component. When a VIP reports a failure,
// the evidence stops at its boundary and the round trip is the vendor's.
module debug_reach #(parameter int SOURCE_IS_READABLE = 0) (
input logic clk, rst_n,
input logic triage,
input logic [15:0] failures, self_debuggable, vendor_days_each,
output logic [15:0] local_cases, escalated, local_days, total_days,
output logic triage_local,
output logic [7:0] n_triages, n_escalated,
output logic opacity_ignored_err
);
logic [31:0] t_q;
// A readable component lets every failure be traced locally.
assign local_cases = (SOURCE_IS_READABLE != 0) ? failures
: ((self_debuggable > failures) ? failures : self_debuggable);
assign escalated = (failures > local_cases) ? (failures - local_cases) : 16'd0;
assign local_days = local_cases;
assign t_q = {16'd0, local_days}
+ ({16'd0, escalated} * {16'd0, vendor_days_each});
assign total_days = (t_q > 32'd65535) ? 16'hFFFF : t_q[15:0];
assign triage_local = (escalated == 16'd0);
// Failures that must leave the building, costed as if they did not.
assign opacity_ignored_err = triage && (failures > self_debuggable)
&& (escalated == 16'd0);
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
n_triages <= 8'd0; n_escalated <= 8'd0;
end else if (triage) begin
n_triages <= n_triages + 8'd1;
if (!triage_local) n_escalated <= n_escalated + 8'd1;
end
end
endmoduleFive triages. Forty failures, a five-day vendor turnaround.
| Traceable locally / turnaround | Local · Escalated · Total days |
|---|---|
| 25 / 5 days | 25 days local · 15 escalated · 100 days — a readable source is 40 |
| 40 / 5 | 40 · 0 · 40 · triage is local |
| 39 / 5 | 39 · 1 · 44 days for one round trip |
| 25 / 1 day | 25 · 15 · 40 days — a one-day turnaround costs nothing extra |
| no failures | 0 · 0 · 0 |
Three triages with an escalation; none when the source is readable.
A VIP failure report ends at the VIP's boundary, and so does your evidence. "Protocol violation on channel 2" with no visibility into the checker that produced it means the first question — is this the DUT or the VIP? — cannot be answered locally. Fifteen of forty failures escalated at five days each is sixty days of waiting inside a hundred-day triage.
Row four is the variable that matters most and is negotiated least. The same fifteen escalations at a one-day turnaround cost forty days total instead of a hundred — the turnaround time, not the escalation count, is what makes opacity expensive. It is a contract term, and it is worth more than most feature comparisons.
Row three is the sensitivity. One failure that cannot be traced locally adds four days to a forty-day triage. Debug visibility is not a nice-to-have with a smooth cost curve; each opaque failure is a fixed multiple of a local one.
Figure 3 — Sixty of the hundred days are waiting rather than working. The multiplier is the vendor's turnaround, which is the term to negotiate and the one that rarely appears in a feature comparison.
12. RTL 8 — An Upgrade Changes Results Before It Improves Anything
// RTL 8 - version churn. A VIP upgrade changes results, and the changes have
// to be triaged before any of them can be believed.
module version_churn #(parameter int UPGRADE_IS_FREE = 0) (
input logic clk, rst_n,
input logic upgrade,
input logic [15:0] tests, newly_failing, real_regressions, hours_each,
output logic [15:0] to_triage, noise, triage_days, churn_pct,
output logic upgrade_clean,
output logic [7:0] n_upgrades, n_costly,
output logic churn_ignored_err
);
logic [31:0] d_q, p_q;
assign to_triage = (UPGRADE_IS_FREE != 0) ? 16'd0 : newly_failing;
assign noise = (newly_failing > real_regressions)
? (newly_failing - real_regressions) : 16'd0;
assign d_q = ({16'd0, to_triage} * {16'd0, hours_each}) / 32'd8;
assign triage_days = (d_q > 32'd65535) ? 16'hFFFF : d_q[15:0];
assign p_q = (tests == 16'd0) ? 32'd0
: (({16'd0, newly_failing} * 32'd100) / {16'd0, tests});
assign churn_pct = (p_q > 32'd65535) ? 16'hFFFF : p_q[15:0];
assign upgrade_clean = (newly_failing == 16'd0);
// Newly failing tests, costed at nothing to sort out.
assign churn_ignored_err = upgrade && (newly_failing != 16'd0)
&& (to_triage == 16'd0);
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
n_upgrades <= 8'd0; n_costly <= 8'd0;
end else if (upgrade) begin
n_upgrades <= n_upgrades + 8'd1;
if (!upgrade_clean) n_costly <= n_costly + 8'd1;
end
end
endmoduleFive upgrades. Two thousand tests, two hours of triage each.
| Newly failing / real regressions | To triage · Noise · Days · Churn |
|---|---|
| 120 / 8 | 120 · 112 noise · 30 days · 6% — the free-upgrade model triages 0 |
| 0 / 0 | 0 · 0 · 0 · clean |
| 8 / 8 | 8 · 0 noise · 2 days · every failure real |
| 8 / 12 reported real | 0, floored · not a wrapped value |
| 1 / 0 | 1 · 1 · 2 hours rounds to no days · still not clean |
Four upgrades with something newly failing — the same four either way, because a failing test is a fact.
An upgrade is a change to the thing that decides whether your design is correct, and every difference has to be explained before any of it is believed. A hundred and twenty newly-failing tests of two thousand is six percent churn and thirty days of triage — of which a hundred and twelve are the VIP now enforcing something differently, and eight are real.
Row three is the good outcome and it is still a cost. Eight newly failing, all eight real: the upgrade found eight bugs, which is exactly what it is for, and it is still two days of work before anybody knows that. There is no upgrade with a triage cost of zero except one that changes nothing.
Row five is the rounding boundary. One test at two hours rounds to no days, and the upgrade is still not clean — the boolean and the day count answer different questions, which is why both outputs exist.
13. RTL 9 — The Licence Is The Part Of Buying That Gets Priced
// RTL 9 - build against buy. A VIP is bought to save the build, and the
// integration, the licences and the churn are the part nobody prices.
module buy_or_build #(parameter int LICENCE_ONLY = 0) (
input logic clk, rst_n,
input logic budget,
input logic [15:0] licence_days, integrate_days, churn_days_yr,
input logic [15:0] build_days, budget_days,
output logic [15:0] buy_total, build_total, saving, overrun,
output logic buying_wins,
output logic [7:0] n_budgets, n_over,
output logic integration_ignored_err
);
logic [31:0] b_q;
assign b_q = (LICENCE_ONLY != 0) ? {16'd0, licence_days}
: ({16'd0, licence_days} + {16'd0, integrate_days}
+ {16'd0, churn_days_yr});
assign buy_total = (b_q > 32'd65535) ? 16'hFFFF : b_q[15:0];
assign build_total = build_days;
assign saving = (build_total > buy_total) ? (build_total - buy_total) : 16'd0;
assign overrun = (buy_total > budget_days) ? (buy_total - budget_days) : 16'd0;
assign buying_wins = (buy_total <= build_total);
// Integration and churn that happen, costed at nothing.
assign integration_ignored_err = budget && (integrate_days != 16'd0)
&& (buy_total == licence_days);
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
n_budgets <= 8'd0; n_over <= 8'd0;
end else if (budget) begin
n_budgets <= n_budgets + 8'd1;
if (overrun != 16'd0) n_over <= n_over + 8'd1;
end
end
endmoduleFive budgets. Twenty licence days, forty to integrate, thirty of churn a year.
| Build cost / budget | Buy · Build · Saving · Overrun |
|---|---|
| 240 / 60 days | 90 · 240 · 150 saved · 30 over budget — licence-only reports 20 |
| 240 / 90 | 90 · 240 · 150 · fits exactly |
| 80 / 90 | 90 · 80 · 0 — buying no longer wins · licence-only still says it does |
| 90 / 90 | 90 · 90 · at exactly equal cost, buying wins |
| 240 / 90, no integration or churn | 20 · 240 · both models agree |
One budget over when the integration is counted; none when it is not.
Buying wins, and it wins by less than the licence price suggests. Ninety days against two hundred and forty is a hundred and fifty days saved — a strong case, and the right decision. The case that gets presented is twenty days against two hundred and forty, which is a different and much stronger claim, and it is the one that sets the budget.
Row one is the shape of the miss. The decision is correct and the budget is thirty days short, because the budget was built from the licence cost and the integration and churn arrive afterwards. That is not a bad purchase; it is a well-made purchase with a badly-made plan.
Row four is the boundary, and it is a policy choice. At exactly equal cost the model says buying wins — the tie goes to the purchase, on the reasoning that a bought component carries the vendor's ongoing maintenance. Reasonable people set it the other way; the point is that it is a decision rather than an arithmetic fact.
14. RTL 10 — A VIP-Based Environment Assembled
// RTL 10 - a VIP-based environment assembled. Everything that must hold before
// "we used a commercial VIP" is a claim about your environment, not the VIP.
module vip_signoff #(parameter int VIP_IS_ENOUGH = 0) (
input logic clk, rst_n,
input logic evaluate,
input logic vip_passes, // the VIP reports no errors
input logic config_reviewed, // every option was read
input logic revisions_aligned, // VIP and DUT read the same revision
input logic rules_covered, // spec rules not in the VIP are checked
input logic check_independent, // the VIP is not the DUT's own reading
input logic cases_reachable, // every error case can be injected
output logic trustworthy,
output logic [5:0] fail_mask,
output logic [7:0] n_eval, n_trusted,
output logic false_assurance_err
);
assign fail_mask[0] = ~vip_passes;
assign fail_mask[1] = ~config_reviewed;
assign fail_mask[2] = ~revisions_aligned;
assign fail_mask[3] = ~rules_covered;
assign fail_mask[4] = ~check_independent;
assign fail_mask[5] = ~cases_reachable;
// The vip-passes build is what a vendor's report says.
assign trustworthy = (VIP_IS_ENOUGH != 0) ? vip_passes : (fail_mask == 6'd0);
assign false_assurance_err = evaluate && trustworthy && (fail_mask != 6'd0);
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
n_eval <= 8'd0; n_trusted <= 8'd0;
end else if (evaluate) begin
n_eval <= n_eval + 8'd1;
if (trustworthy) n_trusted <= n_trusted + 8'd1;
end
end
endmoduleSeven configurations.
| What fails | Mask · Full model · The VIP's report |
|---|---|
| nothing | 000000 · trustworthy · trustworthy |
| 140 options unread — §5 | 000010 · not trustworthy · claims trustworthy |
| a revision gap with 24 rules — §6 | 000100 · not trustworthy · claims trustworthy |
| 60 rules with no checker — §7 | 001000 · not trustworthy · claims trustworthy |
| 12 clauses read the same way — §8 | 010000 · not trustworthy · claims trustworthy |
| 12 error cases nothing injects — §10 | 100000 · not trustworthy · claims trustworthy |
| the VIP reported an error | 000001 · not trustworthy · not trustworthy |
One trustworthy under the full model; six under the VIP's report.
Row five is the one that is hardest to accept, because it is the reason the VIP was bought. A VIP that reads an ambiguous clause the same way your designer did reports no errors and cannot report one — the independence you paid for is exactly what is absent, and no amount of configuration or coverage reveals it.
The report on the right is accurate in all seven rows. The VIP is not broken, not misconfigured in any way it could detect, and not lying. It is answering "did I see a violation of the rules I check, as I was configured, at the revision I was built for" — which is a real and useful question, and not the one on the sign-off form.
These six are not the other chapters' six, and a VIP does not remove any of them. It relocates them: 25.3's vacuity becomes an unread option, 25.5's denominator becomes the vendor's rule list, 25.2's scope becomes the VIP's boundary. Every question in this module still has to be asked; only the person who can answer it has changed.
Figure 4 — The configuration is asked first because it is the cheapest to answer and the most likely to be wrong. Independence is asked fourth and is the hardest, because it needs somebody to read the ambiguous clauses twice on purpose. Every exit above is a VIP reporting no errors.
15. Quantitative Reasoning
Configuration. Two hundred options with sixty read is a hundred and forty unreviewed and four checks silently off; at 198 read it is two.
Revisions. A DUT at revision 3 against a VIP at revision 2 is eighteen rules unchecked and six checked by the old wording — twenty-four of exposure, and three revisions of gap is the same twenty-four.
Rules. Three hundred VIP rules plus eighty of your own less forty shared is 340 of 400 — sixty with no checker and forty checked twice.
Correlated readings. Twelve of twenty ambiguous clauses read the same way is sixty percent of the ambiguity invisible; all twenty is a hundred.
Licences. Forty licences against four hundred machines is fifty waves and 500 minutes against a plan of fifty — and one licence short of the machine count costs a whole wave.
Injection. Sixty error cases with forty VIP-injectable and twelve by hand is twelve nothing can produce and thirty-six days of hand work.
Debug. Fifteen of forty failures escalated at five days each is a hundred days against forty; at a one-day turnaround it is forty.
Churn. A hundred and twenty newly-failing tests of two thousand is six percent churn and thirty days of triage, of which a hundred and twelve are noise.
Buy against build. Ninety days to buy against two hundred and forty to build is a hundred and fifty saved — on a budget built from twenty.
The assembled model. Six properties, seven configurations, one trustworthy. The VIP's report called six trustworthy.
| Quantity | Correct · Broken · Ratio |
|---|---|
| Options reviewed, of 200 | 60 · 0 · every default a decision |
| Rules exposed by one revision of gap | 24 · 0 reported · the whole gap |
| Specification rules with a checker | 340 · 400 assumed · 60 unchecked |
| Ambiguous clauses a VIP can catch, of 20 | 8 · 20 claimed · 60% blind |
| Regression wall clock, 40 licences | 500 min · 50 planned · 10x |
| Error cases reachable, of 60 | 48 · 60 assumed · 12 unreachable |
| Days to triage 40 failures | 100 · 40 assumed · 2.5x |
| Days to triage one upgrade | 30 · 0 counted · all of it |
| Days to adopt a VIP | 90 · 20 budgeted · 4.5x |
| Configurations called trustworthy, of 7 | 1 · 6 · 5 false claims |
16. Assertions
Every check is an explicit comparison against an exact value. Icarus Verilog 13.0 has no concurrent assertion support, so each is a procedural comparison against 1'b1, and every one is an equality.
The output-listing step was run as a script this time rather than by reading. Every model's outputs were extracted, matched to their testbench nets, and checked for an appearance in a chk. It reported nine models with gaps and five of them were real — the other four were parameter-independent nets whose partner was already asserted. Automating the step took twenty minutes and it is now the cheapest check in the flow.
Alongside it: every inclusive threshold at exactly equal, every ceiling on and off its boundary, every floor past it, and both builds asserted on every degenerate case.
Configuration. The disabling-defaults count is driven above and below the unreviewed count, which is where the clamp lives.
chk(fGu == 16'd2, "two unreviewed");
chk(fGo == 16'd2, "so at most two checks can be silently off");Revisions. A gap with no rules behind it is driven, and a VIP ahead of the DUT is asserted to floor rather than wrap.
Rules. The coverage is driven exactly at, one below and above the specification's rule count — the last of those is what exercises the clamp.
chk(oGc == 16'd400,"the coverage clamps at the specification");
chk(oGp == 16'd100,"and a hundred percent, not more");Correlated readings. Zero agreement with and without an independent reading are both driven, which is the only pair that distinguishes independence from an absent second opinion.
Licences. A job count that is an exact multiple of the parallelism and one greater are both driven — the wave boundary.
Injection. Capability above the case count is driven, so the clamp is exercised rather than assumed.
Debug. A one-day vendor turnaround is driven, where the escalation costs nothing extra and triage is still not local.
Churn. More real regressions reported than newly-failing tests is driven and asserted to floor at zero.
Buy against build. A build costing exactly what buying does is driven, at the policy boundary.
The assembled model. Every fail mask is asserted as an exact six-bit value, and each of the six bits is driven false alone.
Totals: 302 checks across two testbenches, 162 on the front five models and 140 on the back five, all passing on the unmutated sources.
17. Mutation Testing
Seventy-nine mutations were injected one at a time. 79 injected, 79 killed, after five survivors and two invalid anchors.
| Mutation class | Killed by |
|---|---|
| The review clamp taken the wrong way | 200 reviewed of 250 claimed — §5 row three |
| The checks-off clamp taken the wrong way | Two off of four possible — §5 row five |
| The error reading the unreviewed count | Four checks off, not 140 options — §5 rows one and four |
| The two revision rule counts swapped | Eighteen unchecked and six wrong — §6 row one |
| The rules-behind-the-gap guard dropped | A gap with nothing behind it — §6 row four |
| The overlap added instead of subtracted | 340 covered, not 420 — §7 row one |
| The coverage clamp taken the wrong way | 500 checkers against 400 rules — §7 row six |
| An empty specification reporting nothing covered | A specification with no rules — §7 row seven |
| The agreement clamp taken the wrong way | Thirty agreements of twenty clauses — §8 row four |
| The independent-reading requirement dropped | No agreement and no second opinion — §8 row six |
| The parallelism clamp taken the wrong way | Forty parallel, not four hundred — §9 row one |
| Waves floored instead of ceiled | Fifty-one waves for 2,001 jobs — §9 row five |
| The bound test reading the machine count | Forty parallel against forty licences — §9 row one |
| The reach clamp taken the wrong way | Seventy capability against sixty cases — §10 row six |
| Hand effort at two days each | Thirty-six days, not twenty-four — §10 row one |
| The local clamp taken the wrong way | Twenty-five local of forty failures — §11 row one |
| The vendor round trip added, not scaled | A hundred days, not fifty-five — §11 row one |
| Hours to days at four | Thirty days, not sixty — §12 row one |
| The integration dropped from the buy total | Ninety days, not fifty — §13 row one |
| Buying requiring a strict advantage | A build at exactly ninety days — §13 row four |
| Each of the six mask bits reading a neighbour | Six configurations, each failing one property alone — §14 |
| Every counter's polarity inverted | Ten pairs of totals — every section |
Four of the five survivors were clamps never driven above their limit, and they are the same shape: min(computed, cap) with a testbench that never makes computed exceed cap. Sections 7, 8, 9 and 10 each had one. The corrective is mechanical — for every clamp, drive the input past the cap once — and it belongs beside the threshold rules rather than being rediscovered per chapter.
The fifth was a dominated guard, again dominated by a clamp. Section 9's machines > licences restates the min that produced parallel. That is eleven dead guards across four chapters, and the clamp has now been the cause of six of them.
Two mutations had anchors that matched nothing and were silently not injected. The harness reported ANCHOR x0 rather than a kill, which is the behaviour to want — a mutation that does not apply is not a mutation that passed — and both were repaired and killed. A campaign that treated an unmatched anchor as a kill would have reported 79/79 while injecting 77.
18. Verification Strategy
What a testbench for an integration model must cover.
Script the output-listing step. Reading the models by hand found one gap per chapter; the script found five in one. Twenty minutes of work, and it is now run before every campaign.
For every clamp, drive the input past the cap. Four of five survivors here. A min whose second operand never binds is an untested branch, and it is the commonest untested branch in this batch.
When a guard follows a clamp, assume it is dead. Six of eleven dominated guards across four chapters have this shape. The clamp already established the condition the guard restates.
Treat an unmatched mutation anchor as a failure of the campaign, not of the mutation. Two here. The harness must distinguish "not injected" from "killed", or the score is a count of successful text substitutions.
The cases where the assumption is right. Every option reviewed. Aligned revisions. Enough rules between the VIP and your own. No shared reading. As many licences as machines. A VIP that injects everything. A readable source. An upgrade that changes nothing. No integration cost. Nine exemptions across nine models — one each, which is unusual and is a property of the subject: every one of these broken builds is what a VIP is supposed to deliver, so each has a real configuration in which it does.
Counters as a second signature. Ten models, ten pairs of totals, differing in six. Four are deliberately equal — §6's n_misaligned, §8's n_correlated, §12's n_costly and §5's own reporting — because a revision number, a shared reading and a failing test are facts about the world rather than about the model reading it.
What a real VIP evaluation needs that these models do not have. A clause-by-clause revision mapping for §6, a graded ambiguity model for §8, and a per-escalation turnaround distribution for §11. All three are abbreviations that preserve the conclusion, and section 26 exercises 2, 4 and 7 are where they come back.
19. Synthesis and Implementation Reality
A VIP's configuration is code, and it belongs under review like code. The practical form is a single configuration file with a comment per non-default setting and an explicit line for every option deliberately left at its default. Sections 5 and 22.
Revision alignment is a build-time check nobody writes. The VIP reports its version and the DUT's specification target is in a document. A script that compares them and fails the build is an afternoon and removes section 6 permanently.
The vendor's rule list is usually in the documentation and rarely in a machine-readable form. Section 7's audit is manual the first time and a maintained spreadsheet afterwards — and it is the deliverable that survives a vendor change, which is the argument for doing it properly once.
Independence cannot be bought, only arranged. Section 8's corrective is procedural: identify the ambiguous clauses, have somebody who did not write the RTL read them, and record the reading. A VIP contributes only where its vendor happened to read differently.
Licence servers queue rather than fail. Section 9's fifty waves appear as a regression that is slow rather than one that is blocked, which is why the licence count is diagnosed late — the symptom is indistinguishable from a busy farm.
Encrypted source is the norm and debug hooks are a feature. Section 11's cost is set by what the VIP exposes — transaction logs, internal state dumps, a debug build — and those are evaluation criteria that outrank feature counts once a project is past bring-up.
20. Silicon Observability
| Counter | Why it matters |
|---|---|
| Non-default configuration settings, with a reason each | §5 — the audit trail that makes the surface reviewable |
| Options left at default, counted explicitly | §5 — the number that is otherwise invisible |
| VIP version and DUT specification target, per run | §6 — a build-time comparison nobody automates |
| Specification rules ticked against the VIP's rule list | §7 — the manual audit, maintained rather than repeated |
| Checks fired by the VIP, per rule, per regression | §7 and 25.3 §6 — a VIP's rules can be vacuous too |
| Ambiguous clauses with a recorded second reading | §8 — the only evidence independence exists |
| Licence wait time, per job, per regression | §9 — the symptom that looks like a busy farm |
| Error cases injected against error cases listed | §10 — the reach number, measured rather than quoted |
| Failures escalated, and days to vendor response | §11 — the multiplier that decides opacity's cost |
| Newly-failing tests per VIP version bump | §12 — the churn budget, from history rather than hope |
"Checks fired by the VIP, per rule, per regression" is the entry that connects this chapter to the rest of the module. 25.3 §6 established that a check which never fires is indistinguishable from one that cannot — and that applies to a vendor's checks exactly as it applies to yours. Most VIPs expose this count and almost nobody reads it.
21. Debug Lab
Symptom. A CXL device signs off with a commercial VIP reporting zero protocol errors across a four-month regression. First silicon fails interoperability at a plugfest against two hosts out of five, on a message type the device emits and the hosts reject.
Step 1 — what does the VIP check? Section 7. The audit against the specification's rule list is done for the first time, in four days. The VIP checks three hundred and twelve of four hundred rules. The rule the hosts are enforcing is one of the eighty-eight.
Step 2 — why that rule. It was added in the specification revision after the one the VIP was built against. Section 6: the DUT targets revision 3 and the VIP reports revision 2. The version strings were both in the release notes and had never been compared.
Step 3 — the configuration. While auditing, the team reads the configuration reference properly for the first time. Section 5. Of two hundred options, fifty-three had been set and a hundred and forty-seven were at defaults. Three of those defaults relax checks the team believed were on.
Step 4 — why nobody hit it in-house. The device's own reference model was written by the same engineer who wrote the RTL, from the same reading of the same clause. Section 8. The VIP, the reference model and the DUT all agree — and the two hosts that reject the message read the clause the other way.
Step 5 — the error injection that was planned and not done. The plan listed sixty error cases. The VIP injects forty. Section 10: the twelve that needed hand-built stimulus were scheduled at thirty-six days, cut in a schedule review, and the message-formation case was among them.
Step 6 — what the sign-off meant. "The VIP reports no errors" was true. It meant: no violation of 312 rules, at revision 2, with 147 options at their defaults, checked by a component that reads the ambiguous clause the way we do. Every clause of that sentence is a limitation nobody had written down.
The finding. One interoperability bug and four independent reasons the environment could not have found it: a rule outside the VIP's list, a revision gap, relaxed defaults, and a correlated reading of the clause that caused it. The VIP was not at fault in any of the four.
The fix. In the RTL, emit the message in the form revision 3 requires. In the environment: upgrade the VIP and budget the churn, add a build-time version comparison, check in the configuration with a reason per line, write checkers for the eighty-eight rules outside the VIP, and have somebody who did not write the RTL read the ambiguous clauses. The last of those is the one that would have caught this, and it is the only one with no tool behind it.
What made this hard. Four months of zero errors was accurate. The report answered a narrower question than the sign-off asked, and the gap between the two questions had never been written down — which is section 14, and it is the whole chapter.
22. Design Review
1. How many configuration options are at their defaults, and which of those relax a check? A hundred and forty-seven unread, three relaxing. Sections 5 and 19.
2. Is the configuration checked in, with a reason per non-default line? Configuration is behaviour and belongs under review. Section 19.
3. What revision was the VIP built against, and what does the DUT target? Two version strings in two documents that nobody compares. Section 6.
4. How many of the specification's rules does the VIP check? 312 of 400, and the number takes four days to produce. Section 7.
5. Who checks the other eighty-eight? That is the deliverable the audit produces. Section 7.
6. Which of the VIP's checks have never fired? A vendor's check can be vacuous too. Sections 20 and 25.3 §6.
7. Which ambiguous clauses have a second, independent reading recorded? The only one of these with no tool behind it. Sections 8 and 19.
8. Which error cases can the VIP inject, and what is the hand-built plan for the rest? Thirty-six days, and it is the first thing cut. Section 10.
9. What is the vendor's escalation turnaround, and is it in the contract? It is the multiplier on every opaque failure. Sections 11 and 19.
10. What does "the VIP reports no errors" establish? Section 14 exists because the answer is the last property only.
23. How This Appears In Real Engineering
A verification engineer integrates the VIP, gets it connecting, and moves on — the defaults that made it connect are the defaults that stay. Section 5 is the direct consequence, and it is a first-week decision that survives to tape-out.
A verification lead makes the buy decision on section 13's arithmetic and is right. The budget is built from the licence line, because that is the line with a number attached, and the forty integration days arrive as a surprise in a project that had already decided.
A project manager hears "we're using a commercial VIP" as a risk reduction, which it is. It is not the risk reduction the sentence implies, and section 14's six properties are the honest version of what was bought.
A vendor's engineer implements the rules customers ask for, at the revision the release targets, with defaults that let the widest range of customers connect. Every broken build in this chapter is that engineer doing their job correctly — the failure is entirely on the reading end.
24. Common Misconceptions
"The VIP checks the protocol." It checks the rules its vendor implemented, at the revision it was built for. 312 of 400 is a good VIP (section 7), and the other 88 are yours whether or not anybody has listed them.
"We're using the VIP as an independent reference model." Only where it disagrees with you for a reason. Twelve of twenty ambiguous clauses read the same way is sixty percent of the interpretation risk invisible (section 8), and reading the same words tends to produce the same reading.
"The defaults are sensible." They are chosen so the widest range of customers can connect. That means permissive (section 5), and permissive means checks off.
"We have four hundred machines, so the regression is fifty minutes." Forty licences means fifty waves and five hundred minutes (section 9) — and it presents as a slow farm rather than as a licence shortage.
"The VIP can inject any error." It injects the ones its vendor implemented. Twelve of sixty needing hand-built stimulus is thirty-six days (section 10), and it is the line item that gets cut.
"Upgrading is just a version bump." A hundred and twenty newly-failing tests and thirty days of triage, of which 93% is noise (section 12). There is no upgrade with a triage cost of zero.
25. Interview Reasoning
"You've integrated a CXL VIP and it reports no errors. What have you established?" The honest answer names the qualifiers: no violation of the rules it implements, at the revision it was built for, under the configuration in force. A candidate who lists those three has understood what a VIP is; one who says "the design is protocol-compliant" has read the report as an answer.
"How would you evaluate two VIPs?" Not on feature counts. Rule coverage against the specification, injection reach, revision currency, and escalation turnaround (sections 7, 10, 6 and 11) — and the last is the one that decides what debug costs for the whole project.
"Is a VIP an independent check on your design?" Only where the readings differ. Where the specification is ambiguous and both read it the same way, the VIP is a mirror (section 8) — so the follow-up worth asking back is: which clauses are ambiguous, and who has read them twice?
"Your regression takes ten times longer than planned. Where do you look?" Licence wait time before machine count (section 9). Forty licences against four hundred machines is a factor of ten, and it presents as a busy farm rather than a shortage.
"Buy or build?" Buy, on these numbers — and present ninety days, not twenty (section 13). A candidate who reaches the right decision with the wrong number has made the purchase and mis-set the budget, which is exactly what happens in practice.
26. Exercises
1. Audit a configuration. Take a VIP's option list and classify each option as affecting a check, affecting performance, or affecting neither. How many are in the first class, and how many of those are at defaults?
2. Map a revision. For two adjacent CXL revisions, list the rules added and the rules whose wording changed. Which of the second kind would produce a false failure against a compliant design?
3. Tick the rule list. Take fifty specification rules and check each against a VIP's documented rule set. Extrapolate the audit's cost to four hundred, and say what the maintained version costs per year.
4. Grade the ambiguity. §8 treats a clause as read the same way or not. Build a three-level model — unambiguous, arguable, genuinely open — and re-derive the blind percentage.
5. Find the wave boundary. For 2,000 jobs of ten minutes, compute wall clock against licence count from 10 to 400 and identify the counts where buying one more licence removes a wave.
6. Plan the injection gap. Given sixty error cases and a VIP covering forty, produce the hand-built stimulus plan with an estimate per case, and state which cases you would cut first if the plan were halved.
7. Model the turnaround. §11 uses a flat vendor turnaround. Replace it with a distribution — most in two days, a tail at fifteen — and re-derive the triage cost. Which statistic should the contract specify?
8. Budget an upgrade. From two prior version bumps, estimate the churn for the next one and state the confidence. What would make you upgrade mid-project anyway?
9. Price buy against build honestly. For your own project, fill in §13's five numbers and state which of them you would have to measure rather than guess.
10. Add the seventh property. Propose one none of §14's six implies, name its section, and construct the configuration where the six hold and it fails. A property that cannot fail alone is not a seventh property.
27. Summary
A VIP moves every question in this module inside a component you cannot read, and the answer comes back as "no errors reported" — which is accurate, and narrower than the sign-off it is used for.
Every default is a decision somebody else made. Two hundred options with sixty read is a hundred and forty unreviewed and four checks silently off — and defaults are permissive by design, because they are chosen so the widest range of customers can connect.
A VIP checks the revision it was built against. One revision of gap is eighteen rules with no checker and six enforced by the old wording — and the second kind is worse, because it fails correct designs and passes incorrect ones.
The vendor's rule list is not the specification's. Three hundred plus eighty of your own less forty shared is 340 of 400 — sixty rules with no checker anywhere, and producing that number takes four days and is the only way to have it.
A VIP built from the same reading agrees with your DUT and with nothing else. Twelve of twenty ambiguous clauses is sixty percent of the interpretation risk invisible to both — and independence is arranged, not purchased.
The licences bound the regression. Forty licences against four hundred machines is fifty waves and five hundred minutes against a plan of fifty, and it presents as a slow farm rather than a shortage.
A VIP injects what its vendor implemented. Twelve cases of sixty needing hand-built stimulus is thirty-six days, and it is the line item that gets cut in a schedule review.
Debug stops at a boundary you cannot read. Fifteen escalations of forty failures at five days each is a hundred days against forty — and at a one-day turnaround it is forty, which makes turnaround the term worth negotiating.
And an upgrade changes results before it improves anything. A hundred and twenty newly-failing tests is thirty days of triage, 93% of it noise — with no version bump whose triage cost is zero.
Buying wins, and by less than the licence price suggests. Ninety days against two hundred and forty is a hundred and fifty saved on a budget built from twenty — a correct decision with a plan that is thirty days short.
Four of five mutation survivors were clamps never driven past their cap, which is now a rule beside the thresholds: for every min, drive the input past the limit once. The fifth was a guard dominated by a clamp — the sixth of eleven with that shape. And two mutations had anchors matching nothing: the harness reported them as not-injected rather than killed, which is the behaviour that keeps a score honest.
"The VIP reports no errors" is one property of six. The report called six of seven configurations trustworthy when one was — and §21 is a device four months green that failed a plugfest on a rule outside the VIP's list, at a revision nobody compared, with a hundred and forty-seven options at their defaults, and an ambiguous clause that the VIP, the reference model and the RTL had all read the same way.
Module 25 closes here. 25.1 asked what a passing suite proves, 25.2 whether a check was wide enough, 25.3 when it sampled and who was told, 25.4 how it paired what it compared, 25.5 what its percentage was a percentage of, and this chapter all five in somebody else's code. Every one of the six ended on the same finding: the report is accurate and the question it answers is narrower than the one being asked.
Continue learning
Related tutorials
- Related topic
VIP — A Trusted Participant, Not an Oracle for Your Design
Verification IP proves your traffic is legal PCIe. It cannot prove your device did what the design intended — and across 200,000 transactions the VIP flagged nothing while the project scoreboard caught 6,061 wrong-destination writes.
- Related topic
CXL-over-UCIe Integration
Composing a CXL-coherent chiplet from three state planes that must agree — memory mapping, coherence ownership, and transport. Why one plane being valid proves nothing about another, why one transaction occupies four tracking entries that are not duplicates, why semantic state must not retire at a transport event, and the three-model scoreboard that attributes a failure to a plane.
- Related topic
UCIe and CXL
Which responsibilities belong to CXL and which to UCIe — why native mapping and streaming are different relationships, the three subprotocols' three different boundary contracts, why a UCIe send is not a CXL completion, the destination decided once and never recomputed, CXL.mem traffic that starves CXL.cache into deadlock, what a UCIe recovery may and may not touch, why a degraded link is slower and not different, and a layer-attribution method for deciding which protocol to blame.
- Related topic
Device-Type Selection Discipline
Selecting a device type is selecting a mode space: a two-engine device is four devices, each with its own obligations. Negotiation that can only reduce, disables that must quiesce, and state that must not outlive its protocol. Seven RTL models, twenty-six mutations, twenty-six killed.
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.
