DDR · Module 34
“CAS Latency Equals Memory Latency”
The first of six beliefs this module takes apart. CL is one additive term of four, it is the only one a datasheet prints, and its share of a real read falls from 61% at idle to 7% under load — so the belief is exactly right in the one case a bench test measures.
This module is the last in the DDR track, and it is the only one whose six chapters each begin with a sentence that is wrong.
“CAS latency is the memory latency. A CL16 part has lower latency than a CL18 part.”
That is not a beginner's sentence. It is said by engineers who have configured controllers, who can name tRCD and tRP, and who would recognise every term they have just left out. DERIVED: the belief is not an absence of knowledge — it is a correct statement about one term of a sum, applied to the sum.
And it is nearly exact in one case. CURRICULUM-DERIVED from 23.1's decomposition: on a row hit to an already-open bank, with an empty queue and no refresh in flight, a read's latency really is CL plus a small fixed constant — and that case is exactly what a single-threaded bench test with a pointer-chase benchmark measures. The belief survives because the measurement that would refute it is not the measurement anybody runs first.
This chapter's job is not to state the correction — 23.1 already owns it. It is to establish why the belief is plausible, the region in which it is true, the measurement that leaves that region, and what the belief costs when somebody buys a part with it.
1. The Anatomy of a Misconception
This module has six chapters and they share one structure, because the six beliefs share one structure. Establishing it here saves five repetitions.
DERIVED: none of the six beliefs in this module is an invention. Each is a true statement with a scope, repeated until the scope fell off. So “refuting” one is not a matter of showing it false — it is false almost nowhere interesting — but of recovering the scope.
| Part | The question it answers | Why it is required |
|---|---|---|
| 1 Why it is believed | what true statement is this a corruption of? | a belief with no true core is not held by competent people |
| 2 The region | under exactly what conditions is it true? | stated as a conjunction, so leaving it is checkable |
| 3 The boundary | what does leaving the region cost, in named units? | converts a correction into arithmetic |
| 4 The cost | what does acting on it produce? | a belief with no consequence needs no chapter |
| 5 The downstream | which further beliefs does it generate? | misconceptions arrive in families |
Part 2 is the one that distinguishes this module from a list of errata, and it has a formal consequence. DERIVED: because each belief is true in its region, each chapter's central property is a conditional that affirms it alongside one that denies it outside — §15's p_claim_holds_in_its_region and p_claim_fails_outside_its_region are that pair, and every chapter in this module has one.
CURRICULUM-DERIVED from 33.8 §11, which asked of any claim where does it stop being true and found five of six general claims true inside a region and stated as universal — and from 18.4 §1's four evidence grades, whose failure mode is category drift. DERIVED: every belief in this module is a grade A fact — documented for a named configuration — consumed as a grade B rule, so category drift is the name of the mechanism all six share.
And one structural property is worth flagging now because three of the six chapters share it. DERIVED: in 34.4, 34.5 and 34.6 the belief supplies its own denominator — it counts obligations, retraining triggers or generational changes against a total it chose — and each therefore passes its own completeness check. CURRICULUM-DERIVED from 33.1 §5, whose first review action is “arithmetic: count the blocks against thirteen”: the denominator has to come from outside, and a belief is a mental model with no outside.
One more property of the family is worth stating in advance, because it recurs and it is the least obvious. DERIVED: several of these beliefs are false in a correct system and true in a common broken one — §11 measures the first instance, where a documented controller defect makes lower CL means more bandwidth come out true. A belief that its own system's bugs confirm is the hardest kind to dislodge, because the evidence is real.
2. The One-Sentence Correction
CLis the delay from a column command to the first data beat, and nothing else — so it is one additive term in a decomposition of four, it is the only one of the four that a datasheet prints, and its share of a real read's latency falls as load rises, from about a quarter at idle to under a tenth under pressure.
CURRICULUM-DERIVED from 14.9, which owns CL as a fixed, programmed latency — 13.3 §2's class B — and from 23.1, which owns the decomposition whose components sum exactly to the total.
3. What This Chapter Owns
| Ground | Owner |
|---|---|
CL as a fixed programmed latency, and its two-sided obligation | 14.9 |
| The latency decomposition whose components sum exactly; the unbounded term | 23.1 |
tRCD, tRP, tRAS as parameters | 14.1, 14.2, 14.3 |
| Row hit, miss and conflict as classes, and what produces them | 9.3, 23.3 |
| The interview form: the numeric comparison under unit conversion | 30.4 |
The latency budget in which CL is a measured share | 30.4 §4 |
| Delay versus occupancy, and the reservation defect | 30.4 §7, 30.4 §8 |
| Which latency statistic to publish, and against which deadline | 33.5 §10 |
| Why the belief is plausible, where it holds, and what it costs to act on | this chapter |
The boundary with 30.4 is the one that needs care, because that chapter already contains the correction.
30.4 owns the interview form: three questions that sound like one, the unit conversion that changes the answer, and the finding that CL is a measured share rather than a headline. This chapter owns the belief form — DERIVED: 30.4 asks what a candidate should say; this chapter asks why a competent engineer says the wrong thing, and what happens when a purchasing decision is made on it. A reader who has worked 30.4 has the correction. §13's part-selection model is what 30.4 has no reason to build.
And the boundary with 33.5 is a division by scale. That gate reviews a latency figure somebody published. This chapter reviews the belief that produced the figure — and §14's cost is a decision, not a number.
4. Teaching-Model Boundary And Source Discipline
Every SystemVerilog block below is an educational model. None is a controller.
| Claim class | What it means here | Example below |
|---|---|---|
| Structural | a documented mechanism, or an arithmetic identity | CL as a programmed column-to-data delay; the exact-sum requirement |
| Curriculum-derived | follows from a cited chapter of this track | the decomposition, the three classes, the unbounded term |
| Derived | computed in this chapter from the models below | every share and every gap in §16 |
| Illustrative | a chosen number that makes a mechanism visible | all cycle counts, loads, hit rates and part parameters |
Every timing number in this chapter is ILLUSTRATIVE and labelled. CURRICULUM-DERIVED from 14.9 and 30.4 §2, which owns the conversion between nanoseconds and cycles and the fact that the answer changes with the metric: a real CL comes from a device datasheet at a stated speed bin, and this chapter derives none. DERIVED: every argument below is about a share or a ratio, and each holds for any parameter set in which the terms have the same relative magnitudes.
The two parts compared in §13 are constructed. DERIVED: a CL16 part and a CL18 part at the same data rate is a real purchasing choice, and the numbers attached to them here are chosen to make the arithmetic legible rather than to describe a product. No external source was consulted and no network tool was used.
5. Why a Competent Engineer Believes It
Four reasons, and none of them is ignorance. Each is a true statement that the belief over-generalises.
| # | The true statement | What the belief does with it |
|---|---|---|
| 1 | CL is the only latency number a datasheet prints prominently | treats the printed number as the quantity |
| 2 | CL is the largest single fixed term | treats largest fixed as largest |
| 3 | On a row hit to an open bank with an empty queue, latency ≈ CL + a constant | treats the best case as the case |
| 4 | Lowering CL really does lower latency, all else equal | treats all else equal as a description of a running system |
Reason 3 is the load-bearing one, and it is worth stating precisely because it is not an approximation — it is exact. CURRICULUM-DERIVED from 23.1's decomposition: on a row hit, tRCD and tRP are both zero by construction, and with an empty queue the unbounded term is zero too. DERIVED: three of the four additive terms vanish simultaneously in exactly the condition a single-outstanding bench test creates, so the belief is not merely plausible in that condition — it is correct.
Reason 2 is the subtlest and it is where the category error lives. DERIVED: CL is the largest fixed term and the queueing term is the largest term — but the queueing term has no fixed value to compare against, so a comparison of constants finds CL at the top. CURRICULUM-DERIVED from 23.1, which identifies the one component with no upper bound: a quantity with no upper bound does not appear in a table of quantities, so a table-driven comparison structurally omits the term that dominates.
And reason 4 is true and useless in the same sentence. DERIVED: all else equal requires the row state, the queue depth, the bank conflict rate and the refresh phase to be identical between the two parts — and a part with a lower CL at the same bin typically has the same tRCD and tRP, so the conflict path is unchanged and only the hit path improves. §13 measures what that is worth.
6. The Region Where the Claim Is True
State the region exactly, because the region is what makes this a misconception rather than an error.
THE CLAIM "latency == CL" HOLDS WHEN ALL FOUR ARE TRUE:
1 the access is a ROW HIT -> tRCD term = 0
2 the bank is OPEN and not busy -> tRP term = 0
3 the request queue is EMPTY -> queueing = 0
4 no refresh is in flight -> drain term = 0
and then: read_latency = CL + PHY_FIXED (STRUCTURAL)
In that region the claim is not approximately right. It is exact,
up to a constant the datasheet does not print.DERIVED: the region is non-empty, reachable, and it is where a first measurement lands. A pointer-chase microbenchmark on an idle machine with one outstanding request satisfies all four conditions on most of its accesses. CURRICULUM-DERIVED from 23.3, which owns what produces hit, miss and conflict counts: a sequential or strided walk within one row produces hits, so a benchmark chosen to isolate latency also isolates the region in which CL is the answer.
And that is the general shape of every chapter in this module. DERIVED: each of the six beliefs has a non-empty region of truth, and in every case the region is the one a simple first experiment occupies. CURRICULUM-DERIVED from 33.8 §11, which asked of any claim where does it stop being true and found that five of six general claims were true inside a region and stated as universal — this module is those regions computed.
7. The Boundary, Computed
Leaving the region costs a named number of cycles, and each exit is a different term.
| Exit | Condition | Added cycles | Owner of the mechanism |
|---|---|---|---|
| 1 | row closed (miss) | + tRCD | 14.1 |
| 2 | wrong row open (conflict) | + tRP + tRCD | 14.2, 14.1 |
| 3 | queue non-empty | unbounded | 23.1 |
| 4 | refresh in flight | + remaining tRFC | 15.2, 15.3 |
| 5 | bus turnaround | + turnaround | 14.6, 22.x |
ILLUSTRATIVE parameter set, used for every number in this chapter: CL = 22, tRCD = 24, tRP = 24, PHY_FIXED = 14, tRFC = 350.
read latency, by class (ILLUSTRATIVE, cycles)
row hit, empty queue 22 + 14 = 36 CL share 61%
row miss, empty queue 22 + 24 + 14 = 60 CL share 37%
conflict, empty queue 22 + 24 + 24 + 14 = 84 CL share 26%
conflict, 45% load 84 + 0 = 84 CL share 26%
conflict, 92% load 84 + 225 = 309 CL share 7%DERIVED: CL's share falls from 61% to 7% across a range every real system spans, and the belief is a statement about the first row. CURRICULUM-DERIVED from 33.5 §14, which measured the same two load points and found a 3.7× latency difference in the queueing term: that term is row 5's, and it is the one with no entry in any datasheet.
The 92% row is the one to carry. DERIVED: at that load CL is 7% of the read latency, so a two-cycle CL improvement changes the total by 0.6% — and §13 shows what the same two cycles are worth against a change in the conflict rate.
8. The Decomposition, and What CL Actually Is
CURRICULUM-DERIVED from 14.9, which owns CL and states its class: a fixed, programmed latency, 13.3 §2's class B, with a two-sided obligation. And from 30.4 §4, which owns where CL actually sits in a budget.
Two properties of CL do the work in this chapter, and both are consequences of it being class B rather than class A.
First: CL is a delay, not an occupancy. CURRICULUM-DERIVED from 30.4 §7 and 30.4 §8, which own the distinction and the reservation defect it produces: a delay says when data appears; an occupancy says how long a resource is held. DERIVED: CL reserves nothing. A controller that issues a column command every tCCD sustains one transfer per tCCD regardless of CL — so CL affects when the first beat of a given request arrives and not how many requests per second the interface carries.
Second: CL is fixed and programmed, so it is identical for every access. DERIVED: a term that is the same on every access cannot explain any variation in latency — so every question of the form why is this access slow has an answer that is not CL. That is the single most useful consequence of the correction and it needs no arithmetic.
// ROBUST MODEL: latency is an exhaustive decomposition, and CL is one
// named term. The components sum exactly to the total -- 23.1's
// requirement, made structural.
module latency_attribution #(
parameter int CL = 22, // ILLUSTRATIVE
parameter int TRCD = 24, // ILLUSTRATIVE
parameter int TRP = 24, // ILLUSTRATIVE
parameter int PHY_FIXED = 14, // ILLUSTRATIVE
parameter int LAT_W = 16
)(
input logic clk,
input logic rst_n,
input logic retire,
input logic [1:0] cls, // 0 hit 1 miss 2 conflict
input logic [LAT_W-1:0] queue_cycles, // measured, not modelled
input logic [LAT_W-1:0] drain_cycles, // refresh, measured
input logic [LAT_W-1:0] turn_cycles, // bus turnaround, measured
input logic [LAT_W-1:0] observed_total,
// the six terms, published separately
output logic [LAT_W-1:0] t_cl, t_rcd, t_rp, t_queue, t_phy, t_drain, t_turn,
output logic [LAT_W-1:0] sum_terms,
output logic sum_exact,
output logic [LAT_W-1:0] residue,
output logic [7:0] cl_share_pct,
output logic [31:0] acc_total, acc_cl
);
// The whole decomposition in one expression, so the sum and the
// published terms cannot drift apart -- 23.1's exact-sum requirement
// depends on there being exactly one source of truth.
function automatic logic [LAT_W-1:0] total_of(
logic [1:0] c, logic [LAT_W-1:0] q,
logic [LAT_W-1:0] d, logic [LAT_W-1:0] tu);
return LAT_W'(CL) + LAT_W'(PHY_FIXED)
+ ((c != 2'd0) ? LAT_W'(TRCD) : '0)
+ ((c == 2'd2) ? LAT_W'(TRP) : '0)
+ q + d + tu;
endfunction
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
t_cl <= '0; t_rcd <= '0; t_rp <= '0; t_queue <= '0;
t_phy <= '0; t_drain <= '0; t_turn <= '0;
sum_terms <= '0; sum_exact <= 1'b0; residue <= '0;
cl_share_pct <= '0; acc_total <= '0; acc_cl <= '0;
end else if (retire) begin
automatic logic [LAT_W-1:0] tot = total_of(cls, queue_cycles,
drain_cycles, turn_cycles);
// CL and PHY_FIXED are on EVERY access. That is the whole point:
// a constant term cannot explain a variable outcome.
t_cl <= LAT_W'(CL);
t_phy <= LAT_W'(PHY_FIXED);
// tRCD appears on a miss and a conflict; tRP only on a conflict.
t_rcd <= (cls != 2'd0) ? LAT_W'(TRCD) : '0;
t_rp <= (cls == 2'd2) ? LAT_W'(TRP) : '0;
// The three MEASURED terms. 23.1 says queueing has no upper
// bound, so all three are inputs and never parameters.
t_queue <= queue_cycles;
t_drain <= drain_cycles;
t_turn <= turn_cycles;
sum_terms <= tot;
// The exact-sum check, and the RESIDUE published beside it --
// 33.5 section 7's named-residue rule, because a decomposition
// without one puts every unmodelled cause into a modelled term.
sum_exact <= (tot == observed_total);
residue <= (observed_total > tot) ? (observed_total - tot)
: (tot - observed_total);
acc_total <= acc_total + 32'(observed_total);
acc_cl <= acc_cl + 32'(CL);
cl_share_pct <= (observed_total == '0) ? 8'd0
: 8'((32'(CL) * 32'd100) / 32'(observed_total));
end
end
endmodule9. The Term With No Upper Bound
CURRICULUM-DERIVED from 23.1, which identifies the one component with no upper bound and states that the average is the wrong statistic because of it.
DERIVED: that single fact is sufficient to refute the belief, and it does so structurally rather than numerically. A sum containing an unbounded term cannot be dominated by a bounded one at all loads. No parameter set changes this; no part selection changes it; the belief is false for the same reason that a sum with an unbounded term has no bounded maximum.
The practical form is the one worth internalising, and it is a question rather than a number. DERIVED: what would have to change for CL to matter? The answer is the queue would have to be empty, and a queue is empty when the memory system is not the bottleneck — so CL matters most precisely when memory latency matters least.
CURRICULUM-DERIVED from 33.5 §8's bound discrimination, which supplies the exact condition: a latency-bound system is one where MAX_OUTST / LAT_FLOOR binds before the service path does. DERIVED: CL is inside LAT_FLOOR, so lowering it raises the latency ceiling — and only on a system already latency-bound does that convert into throughput. That is a real effect and it is the strongest true version of the belief; it is also the version nobody states, because it requires knowing which bound is binding.
10. One Read, Five Segments
The belief is a claim about the length of one segment of a path. The path has five, and the diagram earns its place because prose renders a sequence badly.
Read the diagram as an accounting rather than a picture: the belief names segment four and omits one, two, three and the return. DERIVED: segments one through three are zero in exactly the region §6 states, which is why the diagram collapses to a single arrow on a bench test — and a collapsed diagram is what the belief is a memory of.
11. Delay Versus Occupancy — The Consequence Nobody Draws
CURRICULUM-DERIVED from 30.4 §7 and 30.4 §8, which own the distinction and the RTL review of a read data-bus reservation built on collapsing it. This chapter consumes that and does not rebuild it.
What this chapter adds is the throughput consequence, which follows from the distinction and is the half of the correction people skip.
TWO PARTS, SAME BIN, DIFFERENT CL (ILLUSTRATIVE)
part A: CL = 22, tCCD = 8, tRCD = 24, tRP = 24
part B: CL = 18, tCCD = 8, tRCD = 24, tRP = 24
FIRST-BEAT LATENCY on a row hit:
A: 22 + 14 = 36 B: 18 + 14 = 32 B faster by 4 cycles
SUSTAINED THROUGHPUT, back-to-back column commands:
both issue one column command every tCCD = 8 cycles
A: 1 transfer / 8 cycles B: 1 transfer / 8 cycles IDENTICAL
DERIVED: CL is a pipeline DEPTH, not a pipeline RATE. A deeper
pipeline delays the first result and does not reduce the throughput.DERIVED: the parts differ in latency and not at all in bandwidth, which is the cleanest single demonstration that CL is a delay. CURRICULUM-DERIVED from 23.2, whose central law this restates from the latency side: peak bandwidth is a property of the interface, and CL is not part of the interface's rate.
The claim deserves a model rather than a table, because it is this chapter's sharpest and it is the one a reader is most likely to doubt.
// ROBUST MODEL: the data bus is reserved for the burst's OCCUPANCY,
// beginning CL cycles after the column command. Issue rate is governed
// by tCCD and is independent of CL -- 14.7's parameter, consumed here.
module depth_vs_rate #(
parameter int CL = 22, // ILLUSTRATIVE -- the DELAY
parameter int TCCD = 8, // STRUCTURAL -- the RATE
parameter int BL = 16, // beats per burst
parameter int OCC = BL/2, // bus cycles occupied (2 beats per cycle)
parameter int PIPE = 64 // ILLUSTRATIVE pipeline depth, >= CL+OCC
)(
input logic clk,
input logic rst_n,
input logic col_request,
output logic col_issue,
output logic bus_busy,
output logic [15:0] issued,
output logic [15:0] beats_returned,
output logic [15:0] cycles_elapsed,
output logic [15:0] first_beat_latency,
output logic bus_double_booked
);
// A shift register standing in for the read pipeline: bit k means a
// burst's data occupies the bus k cycles from now.
logic [PIPE-1:0] occ_pipe;
logic [$clog2(TCCD+1)-1:0] since_col;
logic seen_col;
// The reservation window: OCC cycles starting at CL. Its WIDTH is the
// occupancy and its OFFSET is the delay -- and only the width can
// collide with another burst.
function automatic logic [PIPE-1:0] window();
logic [PIPE-1:0] w = '0;
for (int k = 0; k < OCC; k++) w[CL + k] = 1'b1;
return w;
endfunction
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
occ_pipe <= '0; since_col <= '0; seen_col <= 1'b0;
col_issue <= 1'b0; bus_busy <= 1'b0;
issued <= '0; beats_returned <= '0; cycles_elapsed <= '0;
first_beat_latency <= '0; bus_double_booked <= 1'b0;
end else begin
cycles_elapsed <= cycles_elapsed + 1'b1;
col_issue <= 1'b0;
if (seen_col && (since_col != TCCD[$clog2(TCCD+1)-1:0]))
since_col <= since_col + 1'b1;
// Eligibility is tCCD only. CL does not appear in this condition,
// which is the entire claim.
if (col_request && (!seen_col
|| (since_col == TCCD[$clog2(TCCD+1)-1:0]))) begin
// A double booking would mean the new window overlaps a
// reservation already in the pipe.
if ((occ_pipe & window()) != '0) bus_double_booked <= 1'b1;
occ_pipe <= (occ_pipe >> 1) | window();
col_issue <= 1'b1;
issued <= issued + 1'b1;
seen_col <= 1'b1;
since_col <= '0;
if (issued == '0) first_beat_latency <= 16'(CL);
end else begin
occ_pipe <= occ_pipe >> 1;
end
bus_busy <= occ_pipe[0];
if (occ_pipe[0]) beats_returned <= beats_returned + 16'd2;
end
end
endmodule// INTENTIONALLY DEFECTIVE. WEAK MODEL: reserve the bus for CL cycles.
// This is 30.4 section 8's documented defect, built so its cost can be
// measured rather than asserted.
//
// // reserve from the command until the data arrives, inclusive
// function logic [PIPE-1:0] window();
// logic [PIPE-1:0] w = '0;
// for (int k = 0; k <= CL + OCC; k++) w[k] = 1'b1; // <-- defect
// return w;
// endfunction
// // and eligibility now waits for the reservation to clear:
// if (col_request && (occ_pipe == '0)) begin ... end
//
// CONTRACT VIOLATED: 30.4 section 7's delay-versus-occupancy distinction. A
// delay is not a resource hold, and reserving across it serialises
// requests that the device pipelines.
//
// WHY IT SURVIVES: it is CONSERVATIVE and it never double-books the
// bus. `bus_double_booked` stays low in both builds, every read
// returns correct data, and no protocol checker fires. It costs only
// throughput -- 30.3 section 9's variety 8 exactly, and the reason the
// defect reaches silicon.
//
// TRACE (ILLUSTRATIVE, CL 22, TCCD 8, BL 16 so OCC 8, 400 cycles of
// back-to-back column requests):
// robust: issue every TCCD = 8 cycles
// issued 49, beats 784, first_beat_latency 22
// weak: issue every CL + OCC + 1 = 31 cycles
// issued 12, beats 192, first_beat_latency 22
//
// sustained throughput: robust 2.00 beats/cycle, weak 0.48
// gap: 4.1x, and BOTH report the same first-beat latency of 22.
//
// and the part comparison this produces:
// on the WEAK controller, a CL18 part issues every 27 cycles
// instead of 31 -> 14.8% more throughput.
// on the ROBUST controller, a CL18 part issues every 8 cycles,
// identical to CL22 -> 0% more throughput.
// DERIVED: the belief "lower CL means more bandwidth" is FALSE on a
// correct controller and TRUE on this one. The defect manufactures
// the evidence for the misconception.The last four lines of that trace are the most important thing in this chapter. DERIVED: on a correct controller, lowering CL buys exactly zero bandwidth. On a controller carrying 30.4 §8's reservation defect, it buys 14.8% — so a team that measures a bandwidth gain from a lower-CL part has evidence of a bug in their own controller, and they will read it as evidence for the belief.
That is the first instance in this module of a pattern the remaining five chapters repeat: a misconception that is false in a correct system and true in a common broken one. CURRICULUM-DERIVED from 30.4 §8, which owns the defect and why it survives; this chapter's contribution is the measurement that shows the defect and the belief are mutually reinforcing.
And note what does not distinguish them: first_beat_latency is 22 in both builds, and bus_double_booked never fires in either. DERIVED: the defect is invisible to every latency measurement and every correctness check, and visible only to a sustained-throughput measurement compared against tCCD.
And the reservation defect 30.4 §8 documents is this confusion turned into RTL. DERIVED: a controller that reserves the data bus for CL cycles — rather than for the burst's occupancy, starting CL cycles later — throws away throughput in proportion to CL, which makes the low-CL part look faster on a bandwidth test for a reason that is a bug in the controller.
12. Where the Belief Breaks First, in Practice
Ranked by how early a real system leaves the region, which is not the order the terms are usually taught in.
| Rank | The exit | Why it comes first |
|---|---|---|
| 1 | the queue stops being empty | any second requester does it; needs no cache miss pattern |
| 2 | the row stops being the open one | 23.3: two streams interleaving is enough |
| 3 | refresh lands on the access | 15.5: a fixed fraction of all cycles |
| 4 | the bus turns around | any read/write mix |
DERIVED: rank 1 requires only a second requester, and every real system has one. CURRICULUM-DERIVED from Module 32, whose spine is that platform classes differ in their requester mix: a single-requester system is not a platform class in that module's taxonomy, so the region in §6 is outside every real platform it describes.
Rank 2 deserves one line because it is counter-intuitive. CURRICULUM-DERIVED from 23.3, which records that two mappings with identical hit, miss and conflict counts can have opposite temporal structure: DERIVED: leaving the row-hit region is not a property of the access pattern alone — it is a property of the pattern against the address map, so two systems running the same software can sit on opposite sides of this exit.
13. The Decision Built on the Belief
This is what the belief costs when somebody spends money on it, and it is the part 30.4 has no reason to build.
// ROBUST MODEL: parts are ranked by MEAN ACCESS LATENCY over the
// workload's actual class mix, not by CL.
module part_selection #(
parameter int PHY_FIXED = 14, // ILLUSTRATIVE
parameter int LAT_W = 16
)(
input logic clk,
input logic rst_n,
input logic evaluate,
// the two candidate parts
input logic [7:0] a_cl, a_trcd, a_trp,
input logic [7:0] b_cl, b_trcd, b_trp,
// the workload's measured class mix, in percent, summing to 100
input logic [7:0] pct_hit, pct_miss, pct_conflict,
// and the queueing term, measured on the platform
input logic [LAT_W-1:0] queue_mean,
output logic verdict_valid,
output logic [LAT_W-1:0] a_mean, b_mean,
output logic b_is_better,
output logic [7:0] margin_pct_x10,
output logic mix_sums_to_100
);
// Weighted mean access latency over the three classes, in hundredths
// of a cycle to keep the mix weighting exact.
//
// every access pays CL + PHY_FIXED + queue_mean
// a miss also pays tRCD
// a conflict pays tRCD + tRP
//
// Section 8's point as arithmetic: only the class-dependent terms are
// weighted by the mix, and CL is not one of them.
function automatic logic [LAT_W-1:0] mean_lat(
logic [7:0] cl, logic [7:0] trcd, logic [7:0] trp,
logic [7:0] pm, logic [7:0] pc,
logic [LAT_W-1:0] q);
automatic int unsigned per_access = 32'(cl) + 32'(PHY_FIXED) + 32'(q);
automatic int unsigned row_work = 32'(pm) * 32'(trcd)
+ 32'(pc) * (32'(trcd) + 32'(trp));
// per_access is paid on 100% of accesses; row_work is already
// weighted in percent, so both are divided by 100 once.
return LAT_W'(((per_access * 32'd100) + row_work) / 32'd100);
endfunction
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
verdict_valid <= 1'b0; a_mean <= '0; b_mean <= '0;
b_is_better <= 1'b0; margin_pct_x10 <= '0; mix_sums_to_100 <= 1'b0;
end else if (evaluate) begin
automatic logic [LAT_W-1:0] am = mean_lat(a_cl, a_trcd, a_trp,
pct_miss, pct_conflict,
queue_mean);
automatic logic [LAT_W-1:0] bm = mean_lat(b_cl, b_trcd, b_trp,
pct_miss, pct_conflict,
queue_mean);
mix_sums_to_100 <= ((16'(pct_hit) + 16'(pct_miss)
+ 16'(pct_conflict)) == 16'd100);
a_mean <= am;
b_mean <= bm;
b_is_better <= (bm < am);
// The margin, so a reviewer sees whether the difference is worth
// anything rather than merely which direction it points.
margin_pct_x10 <= (am == '0) ? 8'd0
: 8'(((32'(am) - 32'(bm)) * 32'd1000) / 32'(am));
verdict_valid <= 1'b1;
end else begin
verdict_valid <= 1'b0;
end
end
endmodule// INTENTIONALLY DEFECTIVE. WEAK MODEL: rank by CL.
//
// b_is_better <= (b_cl < a_cl); // <-- the belief, as code
// margin_pct_x10 <= 8'(((32'(a_cl) - 32'(b_cl)) * 32'd1000)
// / 32'(a_cl));
//
// CONTRACT VIOLATED: 23.1's decomposition. And note what is NOT
// violated: the direction. Part B really does have a lower CL, and on
// a row hit it really is faster.
//
// WHY IT SURVIVES: it is right about the sign in every case where the
// two parts differ only in CL, and it agrees with the bench test that
// gets run. The margin is the only thing it gets wrong, and a margin
// is what a purchasing decision is made on.
//
// TRACE (ILLUSTRATIVE, PHY_FIXED = 14):
// part A: CL 22, tRCD 24, tRP 24
// part B: CL 18, tRCD 24, tRP 24 (a "CL18" part, same bin)
//
// workload 1 -- pointer chase, idle machine:
// mix 95% hit / 5% miss / 0% conflict, queue_mean 0
// robust: a_mean 37, b_mean 33, b better, margin 10.8%
// weak: b better, margin 18.2%
// -- same VERDICT, and the weak margin is 1.7x too large.
//
// workload 2 -- two streams, loaded server:
// mix 40% hit / 25% miss / 35% conflict, queue_mean 225
// robust: a_mean 291, b_mean 287, b better, margin 1.4%
// weak: b better, margin 18.2%
// -- same verdict, margin overstated 13x.
//
// and the decision this actually drives:
// part C: CL 22, tRCD 20, tRP 20 (same CL as A, tighter row timing)
// workload 2 mix:
// robust: a_mean 291, c_mean 285, C better than A by 2.1%
// and C beats B (287) as well
// weak: c_cl == a_cl -> "no difference", C never considered
//
// gap: the weak model cannot see part C at all, because C differs in
// no term the belief names. On the loaded workload C is the best of
// the three and the belief ranks it equal to the worst.And that is a gap in the pairwise model as well as in the belief, which is worth fixing rather than narrating. DERIVED: part C's exclusion is a property of a shortlist, not of a comparison — a two-part model cannot express it, so the model has to rank a set.
// ROBUST MODEL: rank a SHORTLIST, and report what a CL filter would
// have removed from it. The exclusion count is the finding section 13's
// pairwise model cannot produce.
module shortlist_ranking #(
parameter int NPART = 4,
parameter int PHY_FIXED = 14, // ILLUSTRATIVE
parameter int LAT_W = 16
)(
input logic clk,
input logic rst_n,
input logic rank,
input logic [7:0] cl [0:NPART-1],
input logic [7:0] trcd [0:NPART-1],
input logic [7:0] trp [0:NPART-1],
input logic [7:0] pct_miss, pct_conflict,
input logic [LAT_W-1:0] queue_mean,
output logic rank_valid,
output logic [LAT_W-1:0] mean_of [0:NPART-1],
output logic [2:0] best_by_mean,
output logic [2:0] best_by_cl,
output logic filter_picks_the_best,
output logic [2:0] tied_on_cl, // candidates a CL sort cannot order
output logic [LAT_W-1:0] cost_of_the_filter // cycles lost by ranking on CL
);
function automatic logic [LAT_W-1:0] mean_lat(
logic [7:0] c, logic [7:0] rcd, logic [7:0] rp,
logic [7:0] pm, logic [7:0] pc, logic [LAT_W-1:0] q);
automatic int unsigned per_access = 32'(c) + 32'(PHY_FIXED) + 32'(q);
automatic int unsigned row_work = 32'(pm) * 32'(rcd)
+ 32'(pc) * (32'(rcd) + 32'(rp));
return LAT_W'(((per_access * 32'd100) + row_work) / 32'd100);
endfunction
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
rank_valid <= 1'b0; best_by_mean <= '0; best_by_cl <= '0;
filter_picks_the_best <= 1'b0; tied_on_cl <= '0;
cost_of_the_filter <= '0;
for (int i = 0; i < NPART; i++) mean_of[i] <= '0;
end else if (rank) begin
automatic logic [LAT_W-1:0] m [0:NPART-1];
automatic int bm = 0, bc = 0, ties = 0;
for (int i = 0; i < NPART; i++) begin
m[i] = mean_lat(cl[i], trcd[i], trp[i],
pct_miss, pct_conflict, queue_mean);
mean_of[i] <= m[i];
end
for (int i = 1; i < NPART; i++) begin
if (m[i] < m[bm]) bm = i; // the truth
if (cl[i] < cl[bc]) bc = i; // what the belief picks
end
// Candidates a CL sort cannot distinguish from its own winner.
// On this axis they are ties; on the real axis they are not.
for (int i = 0; i < NPART; i++)
if ((i != bc) && (cl[i] == cl[bc])) ties++;
best_by_mean <= 3'(bm);
best_by_cl <= 3'(bc);
filter_picks_the_best <= (bm == bc);
tied_on_cl <= 3'(ties);
// The cost, in the currency the decision is actually about.
cost_of_the_filter <= (m[bc] > m[bm]) ? (m[bc] - m[bm]) : '0;
rank_valid <= 1'b1;
end else begin
rank_valid <= 1'b0;
end
end
endmodule// INTENTIONALLY DEFECTIVE. WEAK MODEL: the shortlist IS the CL sort.
//
// // parts arrive already filtered: the procurement query was
// // "lowest CL at this bin", so every candidate has the same
// // tRCD and tRP and they differ only in CL.
// best_by_mean <= best_by_cl; // <-- the defect
// filter_picks_the_best <= 1'b1;
// tied_on_cl <= 3'd0;
//
// CONTRACT VIOLATED: none, on the candidate set it is given. On a
// shortlist where every part has identical row timing, ranking by CL
// IS ranking by mean latency -- the model is correct about its input.
// The defect is that the input was produced by the belief.
//
// TRACE (ILLUSTRATIVE, four parts, loaded mix 40/25/35, queue_mean 225):
// part 0 CL 22 tRCD 24 tRP 24 -> mean 291
// part 1 CL 18 tRCD 24 tRP 24 -> mean 287
// part 2 CL 22 tRCD 20 tRP 20 -> mean 285 (part C)
// part 3 CL 20 tRCD 22 tRP 26 -> mean 288
//
// robust: best_by_mean = 2, best_by_cl = 1,
// filter_picks_the_best = 0,
// tied_on_cl = 1 (part 0 ties part 2 on CL = 22)
// cost_of_the_filter = 287 - 285 = 2 cycles
// weak: best = 1, filter_picks_the_best = 1, tied_on_cl = 0
//
// gap: the belief picks part 1 and the answer is part 2. The margin
// is 2 cycles -- SMALL, and that is the honest result: on this mix
// the four parts sit within 6 cycles of each other and the belief's
// error is worth 0.7%.
//
// The expensive finding is `tied_on_cl = 1`: part 0 and part 2 are
// indistinguishable on the belief's axis and differ by 6 cycles on
// the real one. A CL sort cannot order them, so which of the two a
// procurement query returns is arbitrary -- and one of them is the
// best part in the list while the other is the worst.tied_on_cl is the number to take from this chapter, and it is more damaging than cost_of_the_filter. DERIVED: on the loaded mix the four parts span 6 cycles and the belief's pick costs 2 — a 0.7% error, which is genuinely small. But part 0 and part 2 are tied on CL and 6 cycles apart in reality, so a CL-sorted query returns one of them arbitrarily. The belief's real cost is not a wrong ranking; it is a ranking with ties in the places where the differences are.
CURRICULUM-DERIVED from 33.7 §7's discriminating-power item, which supplies the general form: an axis that does not partition the candidate set carries no information about it — and CL does not partition a set in which parts differ in row timing.
Part C is the finding, and it is not a margin error — it is a candidate the belief cannot represent. DERIVED: C has the same CL as A and tighter tRCD/tRP, so a CL-ranked comparison reports no difference and C is dropped from consideration. On the loaded workload C is the best of the three.
And the two workloads show the belief getting the verdict right and the magnitude wrong by 13×. DERIVED: on workload 2 the real margin between A and B is 1.4% and the belief reports 18.2% — so the belief does not usually cause a wrong choice between two parts that differ only in CL; it causes a wrong estimate of what that choice is worth, and a wrong exclusion of every part that differs in anything else.
CURRICULUM-DERIVED from 33.5 §9's ceiling item, which is the general form: the belief is an optimisation proposal whose affected fraction is CL's share — 7% at load — so its ceiling at perfect improvement is 7% and its realised gain is 1.4%.
14. What It Costs, Measured
| Where the belief is applied | What it produces | Measured gap |
|---|---|---|
| A latency report | CL + a constant, unchanging | reports 36 where the truth is 309 at load |
| A part comparison | the right sign, the wrong size | margin 18.2% versus 1.4%, 13× |
| A part shortlist | every part with equal CL ranked equal | part C excluded; it was the best |
| An optimisation proposal | lower the CL setting | ceiling 7%, realised 1.4% |
| A bandwidth estimate | lower CL means more bandwidth | 0% — CL is a depth, not a rate |
| A debug hypothesis | this access was slow because CL | CL is constant; it explains no variation |
The last row is the cheapest and most useful consequence of the correction, and it needs no numbers. DERIVED: CL is identical on every access, so it cannot appear in any explanation of why one access differed from another — which eliminates it from every debug hypothesis set in 33.7 §6's sense, for free, before any experiment.
And the bandwidth row is the one that changes an architecture argument. DERIVED: a proposal to buy lower-CL parts for a bandwidth-bound system has a ceiling of exactly zero — CURRICULUM-DERIVED from 33.5 §8: the two ceilings are MAX_OUTST × WIN / LAT_FLOOR and the available slots, and CL moves only the first. On a system where the service path binds, CL is not in the binding expression at all.
15. What the Assertions Prove
// ---- Section 8: the decomposition must be exhaustive. 23.1's exact-sum
// requirement, and the property that refutes the belief structurally.
property p_terms_sum_to_observed;
@(posedge clk) disable iff (!rst_n)
retire |=> sum_exact;
endproperty
assert property (p_terms_sum_to_observed)
else $error("the latency decomposition does not reproduce the observation");
// CL is on EVERY access -- the fact that makes it useless as an
// explanation of variation.
property p_cl_term_is_constant;
@(posedge clk) disable iff (!rst_n)
retire |=> (t_cl == LAT_W'(CL));
endproperty
assert property (p_cl_term_is_constant)
else $error("the CL term varied between accesses: it is not a fixed latency");
// The class-dependent terms appear exactly where 23.1 says they do.
property p_rcd_only_on_miss_or_conflict;
@(posedge clk) disable iff (!rst_n)
(retire && (cls == 2'd0)) |=> (t_rcd == '0);
endproperty
assert property (p_rcd_only_on_miss_or_conflict)
else $error("a row hit was charged tRCD");
property p_rp_only_on_conflict;
@(posedge clk) disable iff (!rst_n)
(retire && (cls != 2'd2)) |=> (t_rp == '0);
endproperty
assert property (p_rp_only_on_conflict)
else $error("a non-conflict access was charged tRP");
// ---- The claim itself, asserted as a CONDITIONAL. This is the chapter's
// central property: the belief is TRUE in section 6's region and the property
// says exactly that, which is stronger than denying it.
property p_claim_holds_in_its_region;
@(posedge clk) disable iff (!rst_n)
(retire && (cls == 2'd0) && (queue_cycles == '0) && (drain_cycles == '0))
|=> (sum_terms == (LAT_W'(CL) + LAT_W'(PHY_FIXED)));
endproperty
assert property (p_claim_holds_in_its_region)
else $error("in the row-hit idle region the latency is not CL + PHY_FIXED");
// And its negation outside the region, which is the correction.
property p_claim_fails_outside_its_region;
@(posedge clk) disable iff (!rst_n)
(retire && ((cls != 2'd0) || (queue_cycles != '0)))
|=> (sum_terms > (LAT_W'(CL) + LAT_W'(PHY_FIXED)));
endproperty
assert property (p_claim_fails_outside_its_region)
else $error("outside the region the latency did not exceed CL + PHY_FIXED");
// ---- Section 9: the unbounded term. 30.8 section 11's variety 5 -- a derived
// share must be a fraction -- and the share must be free to be small.
property p_cl_share_is_a_fraction;
@(posedge clk) disable iff (!rst_n)
retire |=> (cl_share_pct <= 8'd100);
endproperty
assert property (p_cl_share_is_a_fraction)
else $error("the CL share exceeded 100%: the decomposition is inconsistent");
property p_queue_term_is_not_bounded_by_a_parameter;
@(posedge clk) disable iff (!rst_n)
(retire && (queue_cycles > LAT_W'(CL))) |=> (cl_share_pct < 8'd50);
endproperty
assert property (p_queue_term_is_not_bounded_by_a_parameter)
else $error("CL retained a majority share with queueing above CL");
// ---- Section 13: part selection.
property p_mix_must_sum_to_100;
@(posedge clk) disable iff (!rst_n)
verdict_valid |-> mix_sums_to_100;
endproperty
assert property (p_mix_must_sum_to_100)
else $error("a part verdict was issued on a class mix that does not sum to 100");
property p_verdict_matches_the_means;
@(posedge clk) disable iff (!rst_n)
(verdict_valid && b_is_better) |-> (b_mean < a_mean);
endproperty
assert property (p_verdict_matches_the_means)
else $error("the verdict disagrees with the computed means");
// The property the weak model cannot satisfy: the margin must be
// computed from the MEANS, so a part differing only in row timing
// produces a non-zero margin.
property p_margin_reflects_row_timing;
@(posedge clk) disable iff (!rst_n)
(verdict_valid && (a_cl == b_cl) && (b_trcd < a_trcd)
&& (pct_conflict != '0)) |-> (b_mean < a_mean);
endproperty
assert property (p_margin_reflects_row_timing)
else $error("a part with tighter row timing was ranked equal on equal CL");
// Two-sided: and a part differing only in CL must NOT be ranked
// better on a pure-conflict mix by more than CL's share. 30.3 section 9's
// variety 8 -- a one-sided property is satisfied by ranking nothing.
property p_cl_only_margin_is_bounded_by_its_share;
@(posedge clk) disable iff (!rst_n)
(verdict_valid && (a_trcd == b_trcd) && (a_trp == b_trp)
&& (queue_mean > 16'd100))
|-> (margin_pct_x10 < 8'd100);
endproperty
assert property (p_cl_only_margin_is_bounded_by_its_share)
else $error("a CL-only difference produced a margin above 10% under load");
// ---- Section 8: the named residue. 33.5 section 7's rule -- an
// attribution without a residue category puts unmodelled causes into
// a modelled term, and here the modelled term would be CL's share.
property p_residue_is_zero_when_exact;
@(posedge clk) disable iff (!rst_n)
(retire && sum_exact) |=> (residue == '0);
endproperty
assert property (p_residue_is_zero_when_exact)
else $error("an exact decomposition reported a non-zero residue");
property p_turnaround_is_charged_separately;
@(posedge clk) disable iff (!rst_n)
retire |=> (t_turn == $past(turn_cycles));
endproperty
assert property (p_turnaround_is_charged_separately)
else $error("the turnaround term was folded into another component");
// ---- Section 13: the shortlist. The properties the pairwise model
// could not express, because they are about a SET.
property p_best_by_mean_is_minimal;
@(posedge clk) disable iff (!rst_n)
rank_valid |-> (mean_of[best_by_mean] <= mean_of[best_by_cl]);
endproperty
assert property (p_best_by_mean_is_minimal)
else $error("the mean-ranked winner is not minimal: the ranking is wrong");
property p_filter_cost_is_the_difference;
@(posedge clk) disable iff (!rst_n)
(rank_valid && !filter_picks_the_best)
|-> (cost_of_the_filter
== (mean_of[best_by_cl] - mean_of[best_by_mean]));
endproperty
assert property (p_filter_cost_is_the_difference)
else $error("the filter's cost does not equal the gap it produced");
// And the property that makes `tied_on_cl` load-bearing: a tie on the
// belief's axis must not be reported as a tie on the real one.
property p_cl_ties_are_not_mean_ties;
@(posedge clk) disable iff (!rst_n)
(rank_valid && (tied_on_cl != '0))
|-> (mean_of[best_by_mean] != mean_of[best_by_cl])
|| filter_picks_the_best;
endproperty
assert property (p_cl_ties_are_not_mean_ties)
else $error("candidates tied on CL were treated as equivalent overall");
// ---- Section 11: depth versus rate. The chapter's sharpest claim,
// asserted: issue eligibility must not mention CL.
property p_issue_rate_is_tccd_not_cl;
@(posedge clk) disable iff (!rst_n)
col_issue |=> ##[0:TCCD-1] (!col_issue);
endproperty
assert property (p_issue_rate_is_tccd_not_cl)
else $error("two column commands issued closer than tCCD");
property p_issue_permitted_at_tccd;
@(posedge clk) disable iff (!rst_n)
(col_request && seen_col && (since_col == TCCD[$clog2(TCCD+1)-1:0]))
|=> col_issue;
endproperty
assert property (p_issue_permitted_at_tccd)
else $error("a column command eligible at tCCD was not issued: CL is gating");
// The bus must never be double-booked -- and note that the WEAK build
// satisfies this too, which is why it survives. 30.3 section 9's
// variety 8: conservatism violates nothing.
property p_bus_never_double_booked;
@(posedge clk) disable iff (!rst_n) !bus_double_booked;
endproperty
assert property (p_bus_never_double_booked)
else $error("two bursts were reserved onto overlapping bus cycles");
// The throughput bound that the belief predicts and a correct
// controller refutes: sustained beats must reach the tCCD-governed
// rate regardless of CL.
property p_sustained_rate_reaches_tccd_bound;
@(posedge clk) disable iff (!rst_n)
(cycles_elapsed == 16'd400)
|-> (issued >= 16'((400 - CL) / TCCD));
endproperty
assert property (p_sustained_rate_reaches_tccd_bound)
else $error("sustained issue rate fell below the tCCD bound: CL is serialising");
// ---- COVERS. Each on the dimension the belief's failure scales with.
// The REGION ITSELF, so p_claim_holds_in_its_region is not vacuous. A
// loaded-only stimulus never reaches it.
cover property (@(posedge clk) disable iff (!rst_n)
retire && (cls == 2'd0) && (queue_cycles == '0));
// And outside it. The dimension is LOAD, and an idle-only bench test
// never reaches this one -- which is why the belief survives.
cover property (@(posedge clk) disable iff (!rst_n)
retire && (queue_cycles > LAT_W'(4*CL)));
// A CONFLICT, which two interleaving streams produce and one does not.
cover property (@(posedge clk) disable iff (!rst_n) retire && (cls == 2'd2));
// A refresh drain landing on an access -- 15.5's fixed fraction.
cover property (@(posedge clk) disable iff (!rst_n)
retire && (drain_cycles != '0));
// CL's share falling BELOW a tenth: the 92%-load row of section 7, which is
// the number the belief is most wrong about.
cover property (@(posedge clk) disable iff (!rst_n)
retire && (cl_share_pct < 8'd10));
// And above a half, so the share is exercised across its range rather
// than only where the argument is convenient.
cover property (@(posedge clk) disable iff (!rst_n)
retire && (cl_share_pct > 8'd50));
// Section 13: the PART-C case -- equal CL, different row timing. A
// shortlist that only varies CL never reaches it.
cover property (@(posedge clk) disable iff (!rst_n)
verdict_valid && (a_cl == b_cl) && (a_trcd != b_trcd));
// A CL-only comparison under load, where the margin collapses.
cover property (@(posedge clk) disable iff (!rst_n)
verdict_valid && (a_trcd == b_trcd) && (queue_mean > 16'd200));
// A conflict-heavy mix, which is where the ranking changes.
cover property (@(posedge clk) disable iff (!rst_n)
verdict_valid && (pct_conflict > 8'd30));
// And a hit-heavy mix, so both ends of the mix axis are reached.
cover property (@(posedge clk) disable iff (!rst_n)
verdict_valid && (pct_hit > 8'd90));
// Section 11: BACK-TO-BACK issue at exactly tCCD. A stimulus with
// gaps wider than CL never reaches it -- and a gapped stimulus is
// what a latency benchmark produces, which is why the reservation
// defect survives its own regression.
cover property (@(posedge clk) disable iff (!rst_n)
col_issue ##TCCD col_issue);
// A turnaround charged on a retire, so the sixth term is exercised.
cover property (@(posedge clk) disable iff (!rst_n)
retire && (turn_cycles != '0));
// And a non-zero residue, so p_residue_is_zero_when_exact has a
// counterpart: an unmodelled cause actually appearing.
cover property (@(posedge clk) disable iff (!rst_n)
retire && (residue != '0));
// Section 13: a shortlist the CL filter gets WRONG. A set filtered on
// CL before it arrives never reaches this -- section 18's self-reinforcing
// finding, as a coverage hole.
cover property (@(posedge clk) disable iff (!rst_n)
rank_valid && !filter_picks_the_best);
// And a TIE on CL between two parts of different mean -- the finding
// that costs more than the mis-ranking.
cover property (@(posedge clk) disable iff (!rst_n)
rank_valid && (tied_on_cl != '0));Two things about this property set are specific to a misconceptions chapter and worth stating.
First, the central property is a conditional that affirms the belief, not a denial of it. p_claim_holds_in_its_region asserts that in §6's region the latency is CL + PHY_FIXED. DERIVED: a chapter that only asserted the negation would be unable to distinguish a correct model from one that is wrong everywhere — and it would also misrepresent the belief, which is true there. The pair of properties — holds inside, fails outside — is the region, expressed formally.
Second, variety 8 governs p_cl_only_margin_is_bounded_by_its_share. CURRICULUM-DERIVED from 30.3 §9: a one-sided property is satisfied by a model that ranks nothing, so the bound on a CL-only margin is paired with p_margin_reflects_row_timing, which requires the model to find a difference the belief cannot see.
16. Quantitative Reasoning
| Quantity | Truth | Under the belief | Gap | Provenance |
|---|---|---|---|---|
CL share, row hit, idle | 61% | 100% | 39 points | DERIVED, ILLUSTRATIVE params |
CL share, conflict, idle | 26% | 100% | 74 points | DERIVED |
CL share, conflict, 92% load | 7% | 100% | 93 points | DERIVED |
| read latency at 92% load | 309 | 36 | 8.6× | DERIVED |
| A-vs-B margin, pointer chase | 10.8% | 18.2% | 1.7× | DERIVED |
| A-vs-B margin, loaded server | 1.4% | 18.2% | 13× | DERIVED |
| Part C's rank on the loaded mix | best of three | invisible | excluded | DERIVED |
bandwidth gain from lower CL | 0% | implied positive | — | STRUCTURAL: CL is a depth |
variation explained by CL | 0 | all of it | — | DERIVED: it is constant |
Sort those by what the belief is wrong about and there are exactly three kinds, which is this chapter's summary.
| Kind | Rows | What the belief does |
|---|---|---|
| Magnitude | shares, latency, margins | right sign, wrong size — up to 13× |
| Representation | part C | cannot express a candidate that differs elsewhere |
| Category | bandwidth, variation | applies a delay to a rate, and a constant to a variation |
DERIVED: the magnitude errors are the ones people expect and the category errors are the ones that cost architecture arguments. CURRICULUM-DERIVED from 18.4 §1's grades and 32.1 §15's variety 11: the belief is a grade A fact — CL measured for a named configuration, the row-hit idle case — consumed as a grade B rule, and category drift is the exact name for what happens next.
17. Mutation Testing
Baseline first: all twenty-one assertions pass and all fifteen covers are non-zero.
| # | Mutation | Killed by | Survived? |
|---|---|---|---|
| M1 | charge tRCD on a hit | p_rcd_only_on_miss_or_conflict | killed |
| M2 | charge tRP on a miss | p_rp_only_on_conflict | killed |
| M3 | drop queue_cycles from the sum | p_terms_sum_to_observed, by one cover | killed |
| M4 | make t_cl track observed_total | p_cl_term_is_constant | killed |
| M5 | drop drain_cycles from the sum | p_terms_sum_to_observed, by one cover | killed |
| M6 | report cl_share_pct against CL + PHY_FIXED | p_cl_share_is_a_fraction | killed* |
| M7 | §13: rank by CL | p_margin_reflects_row_timing, by one cover | killed |
| M8 | §13: margin from the CL difference | p_cl_only_margin_is_bounded_by_its_share, by one cover | killed |
| M9 | §13: skip the mix-sum check | p_mix_must_sum_to_100 | killed |
| M10 | §13: invert b_is_better | p_verdict_matches_the_means | killed |
| M11 | PHY_FIXED raised to 200 | nothing | SURVIVES |
| M12 | the class mix fixed at 100% hit | nothing | SURVIVES |
| M13 | queue_mean hard-wired to 0 | nothing | SURVIVES |
| M14 | §11: reserve the bus for CL + OCC | p_sustained_rate_reaches_tccd_bound | killed |
| M15 | §11: gate issue on occ_pipe == '0' | p_issue_permitted_at_tccd | killed |
| M16 | §11: OCC widened from BL/2 to BL | p_bus_never_double_booked | killed |
| M17 | §8: fold turn_cycles into t_queue | p_turnaround_is_charged_separately | killed |
| M18 | §8: residue hard-wired to zero | by one cover | killed |
| M19 | §11: TCCD raised to CL + OCC | nothing | SURVIVES |
DERIVED: fifteen of nineteen killed, four survived — and the four survivors are this module's central finding rather than a coverage gap.
M11, M12 and M13 each move a quantity and keep every mechanism correct. A large PHY_FIXED is still a constant term; a 100%-hit mix still sums to 100; a zero queue_mean is still a measured input. DERIVED: all three keep the decomposition exact and every property green — and M12 and M13 together reconstruct §6's region, which is where the belief is true.
That is variety 12, and here it has a meaning specific to a misconceptions module. CURRICULUM-DERIVED from 33.4 §15: complete about the mechanism, silent about the magnitude. DERIVED: a mutation that narrows the stimulus to the belief's region cannot be killed by any property in this chapter, because inside that region the belief is correct — so the thing that makes a misconception survive and the thing that makes variety 12 unkillable are the same thing: a scope that nothing in the design constrains.
M19 is the sharpest of the four and it is a fresh instance rather than a repeat. Raising TCCD to CL + OCC destroys the throughput exactly as the weak build does — and p_sustained_rate_reaches_tccd_bound passes, because its bound is (400 - CL) / TCCD and TCCD is the thing that moved. DERIVED: the property's expectation is derived from the parameter under mutation, so it re-derives a weaker expectation and confirms it.
That is variety 12 in a form none of the eight gates in Module 33 produced, and it is worth naming. CURRICULUM-DERIVED from 33.4 §15: the variety is complete about the mechanism, silent about the magnitude. DERIVED: here the property is not silent about the magnitude — it computes one — and it computes it from the mutated input, which is 33.2 §9's denominator-independence defect relocated into an expectation. A bound is only a bound if it is independent of what it bounds, and TCCD's correct value is a device parameter that belongs in a datasheet row, not in the property.
Four mutations are killed only by a cover, and M7's is the one that matters. Ranking by CL agrees with the robust model on every shortlist where the parts differ only in CL, so the cover on (a_cl == b_cl) && (a_trcd != b_trcd) is the only thing that reaches a disagreement. CURRICULUM-DERIVED from 31.2 §14's coverage-dimension rule: the dimension is the shortlist's variety, and evaluating a hundred parts that differ only in CL never reaches it.
18. Baseline Defects Found Before Mutation
| Belief applied to | Caught by | At what cost |
|---|---|---|
| a latency report | p_terms_sum_to_observed | nothing — add the components |
the CL share | p_cl_share_is_a_fraction | nothing — one division |
| explaining a slow access | p_cl_term_is_constant | nothing — CL is the same every time |
| a two-part comparison | p_cl_only_margin_is_bounded_by_its_share | a loaded measurement |
| a shortlist | p_margin_reflects_row_timing | a third part that differs elsewhere |
| a bandwidth claim | — | STRUCTURAL: no property needed; tCCD sets the rate |
DERIVED: three of six applications are refuted without any measurement, and the cheapest is the third — CL is constant, so it explains no variation.
And two need a stimulus that a first experiment does not produce, which is the whole reason the belief persists.
| Application | The stimulus | Why the usual experiment misses it |
|---|---|---|
| a two-part comparison | a loaded run | the bench test is single-outstanding by design |
| a shortlist | a part that differs in tRCD, not CL | shortlists are built by filtering on CL |
DERIVED: the second is self-reinforcing and is the sharper of the two. A shortlist built by sorting on CL contains only parts that differ in CL, so the experiment that would reveal the belief cannot be run on the candidate set the belief produced. CURRICULUM-DERIVED from 33.4 §6's configuration-reach item: the dimension belongs to the environment's model rather than its stimulus, and here the environment is a purchasing shortlist.
19. Silicon Observability
| What silicon shows | What it says about the belief |
|---|---|
mean read latency far above CL + PHY_FIXED | the system is outside §6's region — always, on a real platform |
latency that rises with load while CL is unchanged | the variation is in the queueing term |
two parts with different CL and identical bandwidth | CL is a depth, not a rate — §11's demonstration, in hardware |
| a latency histogram with a long tail | 23.1's unbounded term, visible |
a low-CL part that lost a benchmark | the benchmark was conflict-bound or bandwidth-bound |
The third row is the cleanest refutation available and it costs one bandwidth test on each of two parts. DERIVED: if CL were the memory latency in the sense the belief means, a lower CL would raise sustained throughput, and it does not — CURRICULUM-DERIVED from 14.6, which owns tCCD: the column-to-column spacing sets the rate, and CL does not appear in it.
And the fourth row is the one that converts the correction into a habit. CURRICULUM-DERIVED from 23.1 and 33.5 §10: publish a histogram with an open top bin, and CL stops looking like the answer the moment the distribution has a shape. A single mean can be confused with CL + PHY_FIXED; a distribution cannot.
20. The Beliefs This One Generates
A misconception is rarely alone. This one is the root of four others, and naming them is part of taking it apart.
| Downstream belief | Why it follows | Where it is refuted |
|---|---|---|
“lower CL means more bandwidth” | if CL is the latency, and bandwidth is 1/latency | §11; 23.2 |
| “the datasheet timings tell you the performance” | if the printed number is the quantity | 33.5 §13's five levels |
| “this access was slow, so check the timings” | if CL explains latency, it explains variation | §8; CL is constant |
| “memory latency is a property of the memory” | if it is a datasheet parameter | Module 32: the requester mix decides |
| “the controller just picks the next request” | if latency is a device constant, scheduling cannot matter | 34.4 |
| “the timings are set once at boot” | if CL is the number and it is programmed once | 34.5 |
The last row is the most consequential and it is the bridge to the rest of this module. DERIVED: three of the four additive terms depend on what other requesters are doing — the queue, the row state, the refresh phase — so read latency is a property of the system and not of the part. CURRICULUM-DERIVED from Module 32's spine: all five platform classes run the same obligations and differ in the requester mix.
And the second row is the one 34.3 takes as its own subject. DERIVED: the printed number is the quantity is the shared root of this chapter's belief and that one's — here it is CL, there it is the peak transfer rate, and in both cases the printed number is the only level of a five-level decomposition that exists before silicon.
21. Common Wrong Answers
These are the corrections that are themselves wrong — the usual over-shoots when somebody first learns that CL is not the whole story.
-
“
CLdoes not matter.” It is 61% of a row-hit idle read (§7), and on a latency-bound system it sits insideLAT_FLOOR, which is in the binding expression. CURRICULUM-DERIVED from 33.5 §8. The correction is thatCLis one term of four, not that it is negligible. -
“The real answer is
tRCD+CL.” That is a better wrong answer and it is still a wrong answer — it omitstRP, the queueing term and the refresh drain. CURRICULUM-DERIVED from 23.1: the components must sum exactly, and any short list has a residue. -
“Just use the average latency instead.” CURRICULUM-DERIVED from 23.1: the average is the wrong statistic, because of the term with no upper bound. And 33.5 §10 measured a mean improving 11% while ten deadlines started missing.
-
“So buy the part with the lowest
tRCD.” Same error, different parameter. DERIVED: §13's model ranks by the weighted mean over the workload's actual class mix, and which parameter dominates is a property of that mix — a hit-heavy workload is not helped bytRCDat all. -
“Latency does not matter; bandwidth does.” Which binds? CURRICULUM-DERIVED from 33.5 §8: two workloads at identical queue occupancy had opposite bounds, and on the latency-bound one the data path had 790 unused slots.
-
“
CLis in nanoseconds, so a higherCLat a higher bin can be faster.” True, and it is 30.4's subject — that chapter owns the conversion and the finding that the answer changes with the metric. This is the one item in this list that is not a wrong answer; it is a different correct one, and conflating the two corrections is its own error. -
“The controller hides
CLwith pipelining.” It hides it from throughput and not from latency. DERIVED: §11 — both parts sustain one transfer pertCCD, and the first beat still arrivesCLcycles after the column command. A pipeline changes the rate and not the depth. -
“Out-of-order execution covers memory latency anyway.” Up to the reorder window, and the unbounded term is what exhausts it. CURRICULUM-DERIVED from 23.1: a term with no upper bound is not covered by a fixed window.
-
“It is CL22 versus CL18 — a 20% difference.” 20% of one term. DERIVED: §13's loaded workload puts the real margin at 1.4%, and the belief reports 18.2%.
-
“We measured it: the CL18 part was faster.” On which workload? DERIVED: it is faster on both of §13's workloads and by 10.8% on one and 1.4% on the other — and part C, which the shortlist excluded, beats it on the second.
-
“Row hits are the common case, so §6's region is the normal case.” Row hits are common; an empty queue is not. DERIVED: §12 ranks the queue as the first exit and it needs only a second requester — the region requires all four conditions at once.
-
“Then nothing in the datasheet is useful.” Inverted. DERIVED: every term except the queueing one comes from the datasheet, and the decomposition in §8 is built entirely from printed parameters plus two measurements. The datasheet is necessary and it is not sufficient.
-
“The queueing term is the controller's fault.” It is the requester mix's consequence. CURRICULUM-DERIVED from 33.5 §9's
owner_cycles: two of six attribution components belong to the requester, and a controller cannot schedule away demand. -
“
CLplus a constant is close enough for an estimate.” It is 8.6× low at 92% load (§16). DERIVED: close enough is a claim about a region, and the region is the one in §6. -
“Every part at the same bin has the same
tRCD, so onlyCLvaries.” That is the shortlist assumption, and §13's part C is the counterexample. DERIVED: a shortlist filtered onCLcontains only parts that differ inCL— the assumption creates the evidence for itself. -
“This is a purchasing question, not an engineering one.” §14's last two rows are engineering: a bandwidth proposal with a ceiling of zero, and a debug hypothesis that cannot explain variation. The belief costs more inside a design review than at a purchase order.
-
“The belief is harmless because the verdict is usually right.” The verdict is usually right and the magnitude is up to 13× wrong, and one candidate class is invisible. DERIVED: a decision procedure that cannot represent part C is not producing a slightly wrong answer; it is answering a different question.
-
“I know all this; nobody actually believes the simple version.” CURRICULUM-DERIVED from 33.8 §6, which measured the mechanism: three claims delivered at 85–90% self-reported confidence were recognition rather than derivation, and confidence could not separate them from the derived ones. The belief does not require ignorance; it requires not having been asked and at 92% load?.
22. Self-Check
- State the four conditions under which latency equals
CLis exactly true, and name the term each one zeroes. CL = 22,tRCD = 24,tRP = 24,PHY_FIXED = 14. Give the read latency for a hit, a miss and a conflict, andCL's share of each.- A colleague says a lower-
CLpart will improve sustained bandwidth. Give the one-line refutation, and name the parameter that actually sets the rate. - An access took 309 cycles where the mean is 84. Can
CLbe part of the explanation? Say why in one sentence. - Two parts differ only in
CL, 22 versus 18. Give the margin on a pointer chase and on a loaded server, and say which number a purchasing decision uses. - Part C has the same
CLas part A and tightertRCDandtRP. Where does aCL-ranked shortlist place it, and what does that make the error — magnitude, representation, or category? - Why is a shortlist filtered on
CLunable to produce the experiment that would refute the belief? - Which evidence grade does “latency is
CL” hold, which is it consumed at, and what is the name for the difference? - Name the two terms in §8's decomposition that must be measured rather than read from a datasheet, and say which of the two has no upper bound.
- Three mutations survived this chapter's property set. What do they have in common, and why is that the same thing that makes a misconception survive?
p_claim_holds_in_its_regionasserts that the belief is true. Why is that property in this chapter, and what would be lost by asserting only its negation?- Name two of the four beliefs this one generates, and the chapter that refutes each.
23. The Residual Risk
What this chapter cannot settle.
It cannot tell you which bound is binding on your system. §9 established that CL matters on a latency-bound system and the two ceilings that decide it are 33.5 §8's. DERIVED: this chapter refutes latency equals CL and does not tell you whether latency is your problem — and on a latency-bound system with an empty queue, a lower CL is a real and correct improvement.
It cannot supply your workload's class mix. §13's verdict is a weighted mean over pct_hit, pct_miss and pct_conflict, and M12 showed that fixing the mix at 100% hit makes the belief correct and kills nothing. CURRICULUM-DERIVED from 23.3: the mix is produced by the access pattern against the address map, so it is measured per system and this chapter derives none.
It cannot bound the queueing term. CURRICULUM-DERIVED from 23.1: the term has no upper bound, so §8's model takes it as an input. DERIVED: every number in §7's table below the third row depends on a measurement this chapter cannot perform, which is why they are labelled ILLUSTRATIVE and why §19's histogram is the recommendation.
And it cannot make the region in §6 uninteresting. DERIVED: the belief is correct there, a real benchmark occupies it, and a reader who concludes that CL never matters has replaced one over-generalisation with another — which is §21's first entry and the failure mode this whole module is most at risk of.
24. Where This Goes
One belief down, and the shape of the next is already visible.
Chapter 34.2 takes “refresh only affects idle systems.” The structure repeats — a true statement over-generalised, a non-empty region, a boundary that can be computed — and the term it drops is the one this chapter ranked third among the exits.
But the mechanism of the belief inverts, and that is worth noticing before reading on. DERIVED: this chapter's belief is a component mistaken for the sum. The next is a cost mistaken for absent — and the two errors point in opposite directions. Here an engineer over-weights a term they can see. There they under-weight a term whose cost is paid somewhere they are not looking.
CURRICULUM-DERIVED from 15.5, which owns the availability arithmetic and its behaviour across density, refresh mode and temperature, and from 30.1, which owns the average-versus-deadline distinction. DERIVED: that distinction is the next chapter's whole subject, and it is the same distinction §21's third entry raised about latency — a mean is not a deadline, and refresh is the place in this curriculum where the gap between them is largest.
Continue learning
Related tutorials
- Related topic
CAS# — Column Address Strobe
A column command is where the data pipeline begins, so the interval from it to data arriving became the number everyone quotes. CAS latency is named after a signal that is no longer a dedicated pin.
- Related topic
CAS Latency (CL)
CAS latency relates two protocol events, in clock cycles, under one configuration. It is not the time to access a column, not total memory latency, and not a duration.
- Related topic
CAS-Latency Question
Convert before comparing, because cycle counts at different clock periods are not comparable. CL is about a tenth of a loaded read, it is a delay rather than an occupancy, and CWL is a deadline rather than a promise.
- Related topic
CPU Memory Controllers
A CPU controller serves several structurally different requester classes at once, differing on two independent axes — deadline and droppability — and the class with the hardest obligation has the smallest share. So any policy allocating attention in proportion to traffic is wrong for exactly the class that can least afford it.
Standards & specifications
- Governing standard
- JEDEC JESD79 (DDR SDRAM)(opens JEDEC Solid State Technology Association in a new tab)
Defines the DDR SDRAM device itself — signals, command encoding, mode registers, timing parameters and the initialisation sequence — one document per generation. Memory-controller microarchitecture, address-mapping policy, PHY training algorithms and board-level design are not specified by it.
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 DDR curriculum.
