Skip to content
VLSI Mentor

CXL · Module 11

Server Architectures

A server built around expanded memory is a tiered machine. Placement decides latency, hotness counters must saturate and decay, migration must be atomic and rate limited, and local memory is sized to the hot set — not the footprint.

11.3 made a shared device safe: one owner per range, per-host budgets, fair arbitration, contained faults, scrubbed handover.

This chapter takes those mechanisms as given and asks a different question. What does the server actually look like?

1. The Engineering Problem — A Machine With Two Kinds of Memory

Once a server has both local DRAM and expanded memory, it has stopped being a machine with a memory system. It is a machine with two memory systems that share one address space and differ in latency, bandwidth and cost.

That is not a configuration detail. It changes what the word "memory" means to everything above it:

A page now has a location, and the location matters. Two addresses that look identical to software may differ by 3× in access time. Which one a page sits in is now a decision somebody has to make, continuously.

The decision is not static. A workload's hot set moves. A page that was hot at boot may be cold an hour later, and the machine that placed it perfectly at boot is placing it badly now.

Moving a page costs more than leaving it. Migration consumes bandwidth on both tiers and makes the page unavailable while it moves. A policy that migrates too eagerly spends its entire memory bandwidth on movement.

And local memory is no longer sized to the workload. It is sized to the part of the workload that needs to be fast — which is a different, smaller, and much harder number to know.

2. The One-Sentence Model

A tiered server places pages, and placement is a control loop. Measure which pages are hot, move the hot ones close and the cold ones away, do it atomically, and rate-limit the whole thing — because the loop's own cost is paid in the bandwidth it is trying to optimise.

Call it measure, move, but not too often. Every mechanism in this chapter is one term of that loop, and the loop is unstable without all four.

3. What This Chapter Owns

GroundOwner
Why the ceiling exists11.1
Making expanded capacity addressable11.2
Sharing one device between hosts11.3
The tiered server: placement, hotness, migration, sizingthis chapter
What AI workloads demand of it11.5

Deferred:

Deferred groundOwner
Pools across many hosts and devicesModule 12
Fabrics, switches, managersModules 15, 16
Real expander products and mediaModule 17
Latency anatomy and performance modellingModule 18
Rack, row and datacentre architectureModule 23

This chapter is about one node. It has no fabric and no rack. It also introduces NUMA-like placement, page migration and hot/cold classification architecturally — as hardware mechanisms and the state they require — and stops short of operating-system policy, allocator design or scheduler integration, which are software subjects this curriculum does not own.

4. Teaching-model boundary

5. RTL 1 — The Tier Belongs to the Page

Accesses enter a tier router which consults a placement table and sends each access to local memory or expanded memory. The same accesses feed hotness counters. A migration governor reads hotness and decides whether to promote or demote a page, subject to a cooldown and a budget. The migration engine copies the page atomically and then updates the placement table, closing the loop.accessesone address spacetier routerreads placementlocal / expandeddifferent latencyhotnesssaturate + decaygovernorcooldown + budgetmigrationatomic copyobservedif worth12
Figure 1 — the placement control loop. Accesses are routed by a placement table, not by address arithmetic. Hotness counters observe those accesses, a governor decides whether a move is worthwhile and affordable, and the migration engine performs it atomically before updating the table. Every arrow is a mechanism in this chapter, and the loop is unstable if any one is missing.
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
    // The placement table is the authority. Inferring the tier from the page
    // number assumes a layout that migration immediately invalidates.
    t = GUESS_BY_ADDR ? tier_e'((page_id < 4'd8) ? T_LOCAL : T_EXPANDED)
                      : placement[page_id];
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
=== EXP1: the tier is a property of the page, not the address ===
  12 pages, layout matches address : local=8 expanded=4
  routing matched an independent oracle                      : ok
  the guess-by-address variant agrees while layout matches   : ok
  page 2 moved to expanded : correct routes expanded=1 | guess-by-address expanded=0
  the placement table routed the moved page correctly        : ok
  page 3 in motion : correct defer=1 | serve-migrating defer=0 flag=1
  an access to a page in motion was deferred                 : ok

Read the third line carefully: the guess-by-address variant agrees. While the layout matches the address ranges, inferring a page's tier from its address number produces exactly the right answer, and any test written before the first migration passes.

The moment page 2 moves, the two disagree. The placement table routes it to expanded; the address-based guess still says local, and sends the access to memory that no longer holds the page.

This is the defining property of a tiered machine: the tier is state, not a function of the address. A system that treats it as a function is correct until the first migration and wrong forever after.

A page in motion has no home at all. It is not in the old tier — the copy has begun — and not reliably in the new one. The only correct response is to defer the access, and the SERVE_MIGRATING variant that answers anyway was caught reading from a location that is no longer authoritative.

6. Waveform — A Page Changing Tier Under Live Traffic

Ten cycles of access to page five. The placement entry is LOCAL for the first two cycles and the local route is asserted. From cycle three the entry becomes MIGRATING and the defer output asserts while both local and expanded routes stay low, with the deferred counter incrementing each cycle. From cycle seven the entry becomes EXPANDED and the expanded route asserts, with the expanded counter incrementing.locallocalin motion — deferredin motion — deferredexpandedexpandedno home: neither copy is authoritativeno home: neither copy isauthoritativetable updated; accesses resumetable updated; accessesresumeclkplacement[5]LOCLOCMOVMOVMOVMOVEXPEXPEXPEXPto_localto_expandeddefern_local0122222222n_expanded0000000123n_defer0001234444t0t1t2t3t4t5t6t7t8t9
Figure 2 — ten accesses to one page while it migrates. Cycles 1 and 2 route local. From cycle 3 the placement entry reads MIGRATING and every access is deferred rather than served from either copy. From cycle 7 the entry reads EXPANDED and accesses resume against the new home. The deferred count rises by four — the visible cost of an atomic migration.

Teaching-model timing derived from the simplified RTL in this chapter. Not CXL wire timing.

Four cycles in which a perfectly healthy page could not be read. That is the price of atomicity, and it is why migration has to be rare enough to be worth it — the deferral is invisible in throughput averages and extremely visible to whatever was waiting.

7. RTL 2 — Hotness Must Saturate and Decay

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
      if (do_decay) begin
        for (int unsigned p = 0; p < PAGES; p++)
          if (hot[p] != 8'd0) hot[p] <= hot[p] - 8'd1;
      end else if (touch) begin
        // Saturate: a counter that wraps makes the hottest page read coldest.
        if (NO_SATURATE || (hot[page_id] < MAXCOUNT))
          hot[page_id] <= hot[page_id] + 8'd1;
      end
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
=== EXP2: a hotness counter must saturate and decay ===
  20 touches on page 0 : hot=15 (max 15) | no-saturate hot=18
  the counter saturated at its maximum                       : ok
  and was caught exceeding it, so threshold comparisons are meaningless : ok
  after idle decay : hot=13 decays=4 | no-decay hot=15
  an idle page cooled down                                   : ok
  the no-decay variant stayed hot forever                    : ok
  pages 1 and 5 equally hot : p1=15 p5=15 hottest=1
  a tie resolves to the earlier page, not the last one scanned : ok

Two independent requirements, and each fails differently.

Without saturation, the counter runs past its declared maximum — 18 against a stated maximum of 15 — and every threshold comparison built on that scale becomes meaningless. Continue far enough and it wraps, at which point the hottest page in the system reads as the coldest and the placement policy actively moves the wrong page.

Without decay, hotness is a lifetime total rather than a recent rate. A page touched heavily once at startup stays maximally hot forever, and the policy is optimising for a workload phase that ended hours ago. Decay is what makes the metric describe the present.

The tie-break is the subtle one. Two equally hot pages must resolve deterministically, and the natural loop resolves to whichever index was scanned last if the comparison is >= rather than >. That looks like a triviality and is not: under a workload with many equally-warm pages, a last-index bias concentrates every migration decision on one end of the page space.

8. RTL 3 — Migration Must Be Atomic

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
      // Repointing the placement entry before the copy finished exposes a
      // half-copied page as if it were authoritative. A copy that COMPLETES on
      // this very edge is legal, so copied_q -- which this edge is still
      // setting -- cannot be the whole condition.
      if ((st_q == M_COPY) && (st_n == M_SWITCH)
          && !copied_q && !(cnt_q >= COPY_CYCLES[7:0]-8'd1))
        torn_err <= 1'b1;
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
=== EXP3: a migration is atomic from the accessor's view ===
  the migration entered its copy phase                       : ok
  and the page is marked in motion                           : ok
  mid-copy : state=1 commit=0 | switch-early state=0 commit=0 torn=1
  the correct engine has not committed mid-copy              : ok
  the switch-early variant repointed a half-copied page      : ok
  after copy : migrations=1 copy cycles=8 torn=0
  the copy took exactly 8 cycles                             : ok

A page has one home before the migration and one after. During it, none. The placement entry may be repointed only when the copy is complete — repointing early publishes a half-copied page as authoritative, and readers get a mixture of old and new contents with no error anywhere.

A checker that fired on correct behaviour

The first version of this checker read copied_q directly:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
if ((st_q == M_COPY) && (st_n == M_SWITCH) && !copied_q) torn_err <= 1'b1;

It failed the baseline on a correct design. copied_q is set by the same clock edge on which the state transitions, so at the moment of transition it still reads zero — the checker was reading state that the transition it was checking was still creating.

This is the same shape that has now appeared in three separate chapters of this curriculum, in both directions: a checker too narrow to fire on a real violation, and — as here — one too broad, firing on legal behaviour. The corrected condition admits the copy that completes on the transition edge itself.

The general rule is worth stating once: whenever a checker examines a transition, ask which of the values it reads are being written by that same transition.

9. RTL 4 — Migration Must Be Rate Limited

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
    ready  = (NO_COOLDOWN || (cool_q == 8'd0))
             && (NO_BUDGET || (used_q < BUDGET[7:0]));
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
=== EXP4: migration must be rate limited and hysteretic ===
  40 evals oscillating : governed promote=2 demote=2 suppressed=36
  no-cooldown variant  : promote=3 demote=3
  no-budget variant    : promote=20 demote=20 thrash flag=1
  the governor suppressed migrations during cooldown         : ok
  the unlimited variant exceeded its declared budget and was caught : ok
  cold remote page, 20 evals : promotes went 2 -> 2
  a page below the promotion threshold was never promoted    : ok

Forty evaluations of a page oscillating around both thresholds. The governed policy moved it four times; the ungoverned one moved it forty.

Every one of those forty movements consumed bandwidth on both tiers and made the page unavailable while it copied. The policy would have spent the machine's memory bandwidth moving one page back and forth, and the workload would have observed only that memory got slower.

Two independent limiters, because they stop different failures. The cooldown stops a single page oscillating; the budget stops the population of pages from collectively saturating the migration path even when no individual page is thrashing. A design with only one of them fails in the other's direction.

Note the suppressed counter: 36. That number is the policy's own restraint made visible, and it is what distinguishes "the workload is stable" from "the governor is holding back a storm" — two situations that look identical if you only count completed migrations.

A periodic evaluation reads a page's hotness and current tier. If a remote page is above the promotion threshold, or a local page below the demotion threshold, a move is wanted. The decision then passes a cooldown check and a budget check. If both allow it, the migration proceeds and the cooldown is armed. If either refuses, the decision is suppressed and counted rather than dropped silently.noyesyesnoyesnoevaluate pagepast athreshold?leave it alonecooldownexpired?budgetremaining?migrate, armcooldownsuppress, andcount it
Figure 3 — the migration decision, and the two limiters that make it safe. Hotness alone is not sufficient: a page must also pass a cooldown, so it cannot oscillate, and a budget, so the population of marginal pages cannot collectively saturate the migration path. A suppressed decision is counted, which is what distinguishes a stable workload from a governor holding back a storm.

10. RTL 5 — Size Local Memory to the Hot Set

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
    // Hot pages take local memory first; whatever does not fit goes remote.
    hr = (hot_set_gb < local_gb) ? hot_set_gb : local_gb;
    hx = (hot_set_gb > local_gb) ? (hot_set_gb - local_gb) : 16'd0;
    // The right target is the hot set, not the footprint.
    tl = SIZE_TO_FOOTPRINT ? footprint_gb : hot_set_gb;
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
=== EXP5: size local memory to the hot set, not the footprint ===
  local=256 hot=192 footprint=1024 : hot resident=192 hot remote=0 wasted local=64
  the whole hot set fits locally                             : ok
  64 GB of local memory holds cold pages                     : ok
  the right local target is the hot set                      : ok
  the size-to-footprint variant targets the whole footprint  : ok
  local=128 hot=192 : hot resident=128 hot remote=64 undersized flag=1
  64 GB of hot pages were pushed to expanded memory          : ok

This is the sizing question the whole module has been building toward, and it has a precise answer.

Local memory should hold the hot set. Sizing it to the footprint — 1024 GB here — defeats the purpose of expansion entirely: you have bought all the local DRAM you were trying to avoid buying. Sizing it below the hot set — 128 against 192 — pushes 64 GB of genuinely hot pages onto the slow tier, and those pages will be touched constantly.

The interesting case is the first one: 256 local against a 192 GB hot set. It works, and 64 GB of local DRAM is holding cold pages. That is not free — it is the most expensive memory in the machine doing the least valuable job — and it is the number a capacity review should be looking at.

The undersized flag is the alarm that matters, because hot pages on the slow tier is the condition that makes users say the machine is slow, and it is invisible in any average.

11. RTL 6 — Two Tiers, Two Bandwidths

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
=== EXP6: the two tiers have independent bandwidth ===
  both tiers demanded for 32 cycles : local=32 expanded=8 total=40
  serialised variant                : local=32 expanded=0 total=32
  both tiers carried traffic concurrently                    : ok
  independent paths beat a serialised one                    : ok
  serialising cost the expanded tier its share               : ok

40 against 32 — and the whole difference is the expanded tier's contribution, which the serialised design loses entirely.

Expanded memory does not only add capacity; it adds a second independent path to memory. A workload that uses both tiers concurrently gets the sum of their bandwidths. One that places everything in one tier gets that tier's bandwidth and leaves the other idle.

The serialised variant is what a shared queue in front of both tiers does. It is a natural design — one request pipeline, one arbiter, two destinations — and it silently converts two independent bandwidths into one shared one. Here the expanded tier received nothing, because the local tier was always ready and always won.

That is a real architectural constraint on where the queueing structure sits, and it is invisible unless both tiers are driven simultaneously.

12. RTL 7 — Where a Page Lives Versus Why It Moved

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
=== EXP7: separate where a page lives from why it moved ===
  accesses=30 expanded=10 promotes=3 demotes=3 churn=3
  access counts matched an independent oracle                : ok
  expanded accesses are a strict subset of all accesses      : ok
  churn was recorded on every cycle that moved a page both ways : ok
  merge-tiers variant : expanded=30 of 30 accesses
  count-always abuse : expanded=279 accesses=0 flag=1

Access counts describe placement. Migration counts describe policy. Confusing them hides the failure mode that matters most.

A machine with 30% of accesses hitting expanded memory might be perfectly placed — that could be exactly the cold fraction — or it might be badly placed and thrashing. Access counts alone cannot tell. What separates them is churn: promotions and demotions of the same page class occurring together, which is the signature of a policy fighting itself.

Churn is the counter that would have caught the ungoverned policy in §9. Its access distribution would have looked reasonable throughout, while it moved a page forty times.

13. Quantitative Reasoning

Illustrative, with stated assumptions. No figure describes a real product.

The placement equation

With a fraction p of accesses served from expanded memory, and using 11.2's illustrative 80 ns local and 250 ns expanded:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
L_avg = (1 - p) x 80 ns + p x 250 ns
Hot set fits locally?pMean access
entirely0.0588.5 ns
mostly0.20114 ns
poorly0.50165 ns

Placement quality is the whole difference between 88 ns and 165 ns on identical hardware. No component changed; only which pages sat where.

What a migration costs

From §6 and §8: 8 copy cycles, 4 cycles of deferred access.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
cost per migration = copy bandwidth + deferral of accesses to that page
benefit per migration = (accesses after) x (L_expanded - L_local)

A migration pays for itself only if the page is touched enough afterwards. With a 170 ns saving per access, a migration costing the equivalent of 100 accesses needs the page touched more than 100 times before it cools. That is the arithmetic behind the promotion threshold — not a tuning constant but a break-even point.

Thrash cost

From §9: 40 evaluations, 4 governed migrations, 40 ungoverned.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
governed   :  4 migrations, 36 suppressed
ungoverned : 40 migrations
ratio      : 10x the migration bandwidth for the same workload

Ten times the movement for a page that ends up where it started. Migration bandwidth comes out of the same budget as the workload's own traffic, so the cost is not merely wasted — it is subtracted from useful work.

Sizing local memory

From §10, with a 192 GB hot set:

Undersized — hot pages forced onto the slow tier:

LocalHot remote
128 GB64 GB
192 GB0 GB

Oversized — local memory holding cold pages:

LocalWasted
192 GB0 GB
256 GB64 GB

At 192 GB — exactly the hot set — both columns are zero, which is the only configuration that wastes nothing in either direction.

The optimum is the hot set, and both directions cost. Undersizing puts hot pages on the slow tier; oversizing puts the machine's most expensive memory under cold pages. The hot set is measurable — it is 11.1's distinct-page count over a window — which is what makes this a calculation rather than a guess.

Aggregate bandwidth

From §11: local 32, expanded 8 over 32 cycles.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
independent paths : 32 + 8 = 40 accesses
serialised path   : 32 + 0 = 32 accesses
uplift            : 25%

Expansion adds bandwidth as well as capacity, but only if the request path lets both tiers work at once. A shared queue converts a 25% uplift into nothing.

14. Assertions

Icarus Verilog 13.0 is the only simulator installed. It does not execute concurrent SVA — property blocks are unsupported, unique/priority qualities are parsed but ignored — so every property below is synthesisable checker logic verified procedurally, not executed SVA. 45 assertions.

Safety

PropertyIntent
Placement authorityrouting follows the table, never the address
Motion deferrala page in motion is never served
Counter saturationhotness never exceeds its declared maximum
Deterministic tie-breakequal hotness resolves to the earlier page
Atomic migrationthe table is repointed only after the copy completes
Rate limitingmigrations never exceed the declared budget
Threshold respecteda page below the promotion threshold is not promoted
Sizing honestyhot pages forced remote are reported
Rate integrityneither tier accepts beyond its service rate
Tier splitexpanded accesses are a subset of all accesses

Liveness

PropertyAssumption it needs
A deferred access eventually proceedsthe migration completes
A migration eventually commitsthe copy makes progress
A suppressed migration eventually runsthe cooldown expires and budget refreshes

Performance goals — not correctness

GoalMeasured by
Expanded access fraction as plannedexpanded over total
Migration rate sustainablemigrations per window
Churn lowpromote-and-demote coincidences
Local memory not wastedlocal size minus hot set

15. Mutation Testing

Twenty-five mutations. Twenty-five killed.

MutationResult
Placement table ignored, everything routed localkilled
A page in motion is never deferredkilled
Serving a page in motion not reportedkilled
Every access counted as expanded (router)killed
Hotness counter never saturateskilled
Decay never reduces a counterkilled
Counter overrun not reportedkilled
Hottest page selection biased to the last indexkilled
Page never marked in motionkilled
Copy cut shortkilled
Torn page not reportedkilled
Migrations counted per copy cyclekilled
Neither cooldown nor budget appliedkilled
Promotion threshold ignoredkilled
Suppressed migrations not countedkilled
Budget checker guarded by the fault it detectskilled
Hot set assumed to fit regardless of local sizekilled
Hot pages pushed remote never reportedkilled
Local memory targeted at the whole footprintkilled
Undersized local memory not reportedkilled
The two tiers always serialisedkilled
Expanded traffic counted on the requestkilled
Every access counted as expanded (counters)killed
Policy churn never recordedkilled
Tier-split law disabledkilled

First run: 21 of 25. Two assertion-precision gaps, one stimulus gap, one checker needing an abuse instance — the same distribution as the three chapters before it.

The hottest output was never asserted. It was computed, it was correct, and nothing checked it, so a >= comparison biasing the selection to the last-scanned index passed. Killing it needed a deliberate tie between two pages, which is a stimulus most workloads never produce and no random test constructs on purpose.

The promotion threshold was never tested against a cold page. Every evaluation in the original stimulus had hotness above the threshold whenever the page was remote, so a design ignoring the threshold entirely behaved identically.

The budget checker needed the unlimited instance asserted. It was present and never checked.

A real RTL defect, found by the baseline

The torn-page checker described in §8 failed on a correct design because it read copied_q on the edge that sets it. That is a genuine design defect in the checker, not a testbench problem — and it was caught by the baseline run rather than by mutation testing, which is now the fourth such case in this curriculum. Mutation testing verifies the checkers; only running legal stimulus verifies the design.

Two testbench defects

An assertion about wrapping that could not occur. The no-saturate variant was asserted to "wrap and read colder", but with 20 touches on an 8-bit counter it reached 18 — it exceeded its declared maximum without wrapping. The assertion was rewritten to check what actually happens and matters: the counter passes its stated maximum, so every threshold comparison built on that scale is meaningless.

A serialisation test where nothing contended. The two tiers were configured with rates that never collided, so serialising them cost nothing and the test proved nothing. Reconfiguring so the local tier is ready every cycle made the contention real — and the expanded tier then received zero.

16. Verification Strategy

AreaApproach
RoutingLayout matching and then contradicting the address; a page in motion; guess-by-address and serve-migrating variants
HotnessSaturation past the maximum; idle decay; a deliberate tie; no-saturate and no-decay variants
MigrationMid-copy inspection; full copy; a switch-early variant
GovernorA page oscillating around both thresholds; a cold remote page; no-cooldown and no-budget variants
SizingHot set fitting and not fitting; a size-to-footprint variant
BandwidthBoth tiers demanded simultaneously with real contention; a serialised variant
CountersIndependent oracle; merge-tiers and count-always abuse instances

The reference model is a placement table maintained independently in the testbench, updated only when the design commits a migration. Comparing the design's routing against a table the testbench derived from the address would reproduce exactly the defect the chapter is about.

The coverage cross is page tier × hotness band × governor state: local/expanded/migrating, crossed with cold/warm/hot, crossed with ready/cooldown/budget-exhausted. The migrating × hot × budget-exhausted point is a page being accessed heavily while in motion and unable to be moved again — where deferral, thrash and starvation interact — and only directed stimulus reaches it.

17. Synthesis and Implementation Reality

StructureImplementation consequence
Placement tableone entry per page; a real system needs it in DRAM with a cache, not flops
Table lookupin the access path — either a cycle of latency or a critical-path risk
Hotness countersone saturating counter per tracked page; the dominant area cost
Decay sweeptouches every counter; either a slow background walk or wide logic
Hottest scana comparator tree over all pages — depth grows with page count
Migration enginea copy sequencer plus bandwidth on both tiers
Governora cooldown counter, a budget counter and two comparators
Tier countersone bank per tier plus the churn detector

The hotness array is the honest scalability limit. One counter per page is impossible at real page counts, and production tiering uses sampling, hashing or coarse region counters instead. The invariants taught — saturate, decay, deterministic tie-break — survive that change of mechanism; the implementation shown does not scale, and the chapter says so rather than implying otherwise.

The decay sweep is the structure people underestimate. Decaying every counter periodically is either a wide parallel operation or a background walk that takes many cycles, and if the walk is slower than the workload's phase changes the metric lags reality.

18. Silicon Observability

CounterDiagnoses
accesses by tierwhere traffic actually goes
deferred accessesthe visible cost of migrations in flight
hot set sizewhether local memory is correctly sized
hot pages resident remotelythe condition users experience as slowness
wasted local capacityexpensive memory holding cold pages
promotions and demotionspolicy activity
churna policy fighting itself
suppressed migrationsrestraint the governor is exercising
migration copy cyclesbandwidth spent on movement rather than work
served_migrating, torncorrectness alarms — must be zero forever
wrap, thrash, tier_splitcorrectness alarms — must be zero forever

The pair to fight for is hot-pages-resident-remotely against wasted-local-capacity. Together they say whether local memory is the right size and in which direction it is wrong — the single most consequential sizing decision in a tiered server, and one that no average reports.

Churn against completed migrations is the second pair. High churn with low net movement means the policy is oscillating; that is the field signature of a missing cooldown, and it costs one comparator to detect.

19. Debug Lab

1

Accesses going to memory that no longer holds the page

ADDRESS-INFERRED-TIER
Symptom

A tiered server works correctly at boot and develops intermittent wrong-tier routing over hours. Latency for specific pages is wrong and occasionally data is stale. Rebooting fixes it for a while.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  page 2 moved to expanded : correct routes expanded=1 | guess-by-address expanded=0
  the placement table routed the moved page correctly         : ok
Evidence

Compare the tier the router selected against the placement table for the same page. If they differ, the router is not consulting the table.

Likely Causes

Tier inferred from the address range; the table consulted but a cached copy used; the table updated by migration but the router reading a stale shadow.

Debug Sequence

Migrate one page deliberately and re-access it. The router must follow the table. Then check whether the defect correlates with migration count — it appears only after the first migration, which is why boot-time testing misses it.

Root Cause

The tier is state, not a function of the address. An address-derived tier is correct until the first migration and wrong forever afterwards.

Fix
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
t = placement[page_id];   // the table is the authority
Prevention

Test routing after a migration, not before. A layout that matches the address ranges makes the correct and broken designs indistinguishable.

2

Readers see a mixture of old and new page contents

TORN-MIGRATION
Symptom

During periods of high migration activity, applications observe data corruption within single pages — part old, part new. No error is reported. It correlates with migration rate, so a quiet system is clean.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  mid-copy : state=1 commit=0 | switch-early state=0 commit=0 torn=1
  the switch-early variant repointed a half-copied page       : ok
Evidence

Check whether the placement entry can be repointed before the copy completes. If the commit and the copy-complete are separate conditions, they can be reordered.

Likely Causes

Commit driven by state entry rather than copy completion; the copy-complete flag read on the same edge it is set; accesses served from either copy during the move.

Debug Sequence

Inspect the commit signal mid-copy. It must be low. Then confirm that accesses during the copy are deferred rather than served from the old location.

Root Cause

The page was published as authoritative before its contents were complete. A page has one home before and one after; during the copy it has none.

Fix
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
M_COPY: if (cnt_q >= COPY_CYCLES-1) st_n = M_SWITCH;   // complete first
commit = (st_q == M_SWITCH);                            // then repoint
Prevention

Assert that commit implies copy-complete — and when writing that assertion, check whether the completion flag is being set by the same edge the checker examines.

3

Memory bandwidth spent moving one page back and forth

MIGRATION-THRASH
Symptom

A tiered server's throughput is well below both tiers' combined capability. Neither tier looks saturated by workload traffic. Migration activity is continuous, and the workload appears stable.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  40 evals oscillating : governed promote=2 demote=2 suppressed=36
  no-budget variant    : promote=20 demote=20 thrash flag=1
Evidence

Compare promotions against demotions of the same pages. Roughly equal counts with no net movement is thrash — the policy is fighting itself.

Likely Causes

No cooldown after a migration; promote and demote thresholds too close together; no budget, so many marginal pages move at once.

Debug Sequence

Read the churn counter and the suppressed count. High churn with low suppression means no rate limit exists. Then widen the threshold gap and add a cooldown, and re-measure.

Root Cause

Migration bandwidth comes from the same budget as workload traffic, so movement is subtracted from useful work. In the measured run the ungoverned policy moved a page ten times as often for the same end state.

Fix
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
ready = (cool_q == 8'd0) && (used_q < BUDGET);   // both limits, both needed
Prevention

Instrument suppressed migrations. Without it, a stable workload and a governor holding back a storm look identical.

4

The hottest page in the system reads as the coldest

COUNTER-WRAP
Symptom

The tiering policy demotes the most heavily accessed page in the workload and promotes an idle one. The behaviour is reproducible and looks deliberate. Reducing the access rate makes it disappear.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  20 touches on page 0 : hot=15 (max 15) | no-saturate hot=18
  and was caught exceeding it, so threshold comparisons are meaningless : ok
Evidence

Check the counter against its declared maximum. A value above it means every threshold comparison is operating on a different scale than intended, and continued counting will wrap.

Likely Causes

No saturation on increment; counter width smaller than the maximum implies; thresholds defined against a scale the counter does not respect.

Debug Sequence

Touch one page continuously and watch its counter. It must stop at the maximum. If it continues, the scale is broken before any wrap occurs.

Root Cause

An unsaturated counter first invalidates the scale and then wraps, at which point the hottest page reads coldest and the policy actively moves the wrong page.

Fix
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
if (hot[page_id] < MAXCOUNT) hot[page_id] <= hot[page_id] + 8'd1;
if (hot[page_id] > MAXCOUNT) wrap_err <= 1'b1;
Prevention

Assert the impossible value. A hotness counter above its declared maximum is a broken metric before it is a wrapped one.

5

A policy optimising for a workload phase that ended hours ago

NO-DECAY
Symptom

Placement is excellent shortly after start-up and degrades steadily. Pages that were hot during initialisation remain in local memory indefinitely while the current hot set sits remote.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  after idle decay : hot=13 decays=4 | no-decay hot=15
  an idle page cooled down                                    : ok
  the no-decay variant stayed hot forever                     : ok
Evidence

Stop touching a page and watch its hotness. If it does not fall, the counter is a lifetime total rather than a recent rate.

Likely Causes

No decay mechanism; decay interval far longer than the workload's phase duration; the decay sweep not reaching every counter.

Debug Sequence

Compare the reported hot set against a freshly measured distinct-page count over a recent window. A large divergence means the metric is describing the past.

Root Cause

Hotness must describe the present. Without decay it accumulates forever, and a page touched heavily once outranks a page being touched now.

Fix
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
if (do_decay) for (p...) if (hot[p] != 0) hot[p] <= hot[p] - 1;
Prevention

Choose the decay interval against the workload's phase duration, and verify the sweep reaches every counter — a walk slower than phase changes lags reality just as badly as no decay.

6

Expanded memory adds capacity and no bandwidth

SERIALISED-TIERS
Symptom

Adding expanded memory increases capacity as expected and leaves aggregate bandwidth unchanged. Both tiers are healthy in isolation. The expanded tier shows almost no traffic under mixed load.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  both tiers demanded for 32 cycles : local=32 expanded=8 total=40
  serialised variant                : local=32 expanded=0 total=32
Evidence

Drive both tiers simultaneously and compare aggregate throughput against the sum of their individual rates. Equal to the larger one alone means the paths are serialised.

Likely Causes

A shared request queue in front of both tiers; a single arbiter that always favours the faster path; one outstanding pool covering both tiers.

Debug Sequence

Measure each tier alone, then together. If the combined figure is not close to the sum, find the shared structure — it is usually a queue or an arbiter, not the tiers themselves.

Root Cause

Expansion adds a second independent path to memory. A shared queue converts two bandwidths into one, and the faster tier wins every arbitration.

Fix

Give each tier its own request path and outstanding pool, so both can be in flight simultaneously.

Prevention

Never benchmark tiers one at a time. Single-tier testing cannot reveal a shared bottleneck, and single-tier testing is the default.

7

Hot pages living on the slow tier while local memory sits half empty

MIS-SIZED-LOCAL
Symptom

Users report the machine is slow. Local memory utilisation is around 60%. Expanded memory is heavily accessed. Every capacity metric says there is headroom.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  local=128 hot=192 : hot resident=128 hot remote=64 undersized flag=1
  64 GB of hot pages were pushed to expanded memory           : ok
Evidence

Compare hot set size against local capacity. Hot pages resident remotely is the number; local utilisation is not, because cold pages occupy local memory too.

Likely Causes

Local memory sized to a fraction of the footprint rather than to the hot set; the hot set larger than measured; cold pages never demoted, so they occupy local memory the hot set needs.

Debug Sequence

Measure the hot set as a distinct-page count over a window. Compare with local capacity. If the hot set exceeds it, the sizing is wrong regardless of what utilisation says.

Root Cause

Local memory must hold the hot set. Utilisation cannot distinguish local memory full of hot pages from local memory full of cold ones — and only the first is doing useful work.

Fix
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
hx = (hot_set_gb > local_gb) ? (hot_set_gb - local_gb) : 16'd0;
if (hx != 16'd0) undersized_err <= 1'b1;
Prevention

Report hot-pages-resident-remotely as a first-class metric. It is the condition users experience as slowness and it is invisible in utilisation.

8

Every migration decision lands on the same end of the page space

TIE-BREAK-BIAS
Symptom

Under a workload with many equally-warm pages, the tiering policy repeatedly selects pages from one region and ignores an equally hot region entirely. The distribution looks deliberate and no rule explains it.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  pages 1 and 5 equally hot : p1=15 p5=15 hottest=1
  a tie resolves to the earlier page, not the last one scanned : ok
Evidence

Construct a deliberate tie between two pages and observe which is selected. If it is always the higher index, the comparison is >= rather than >.

Likely Causes

A scan updating the winner on equality; a scan direction that favours one end; no defined tie-break at all.

Debug Sequence

Make two pages exactly equal and above every other page. Check the selected index. Then reverse their positions and confirm the rule is consistent.

Root Cause

>= updates the winner on a tie, so the last-scanned page always wins. With many equally-warm pages, that concentrates every decision at one end of the page space.

Fix
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
if (hot[p] > hot[hottest]) hottest = p;   // strict: earlier index wins ties
Prevention

Assert the tie-break explicitly. Ties are common in real hotness distributions and no random test constructs one deliberately.

20. Design Review

  1. Where does the router get a page's tier — a table, or the address?
  2. What happens to an access issued while its page is migrating?
  3. Do hotness counters saturate, and what is the declared maximum?
  4. How often do they decay, and how does that compare with the workload's phase duration?
  5. How is a tie between equally hot pages resolved?
  6. Can the placement table be repointed before a copy completes?
  7. What limits the migration rate — a cooldown, a budget, or both?
  8. What is the gap between the promote and demote thresholds?
  9. Is local memory sized to the hot set or to the footprint?
  10. Can both tiers be in flight simultaneously, or do they share a queue?
  11. Does any counter distinguish good placement from a policy that is thrashing?

21. How This Appears in Real Engineering

Architect. Owns the local:expanded ratio, and must get the hot set from measurement rather than assumption. Sizing to the footprint defeats the purpose; sizing below the hot set defeats the machine.

RTL designer. Owns the placement table lookup in the access path and the hotness array's area. The decay sweep is the structure most often underestimated.

DV engineer. Owns the post-migration tests. Routing, tie-breaks and torn pages are all invisible before the first migration, and boot-time testing is the default.

Firmware engineer. Owns the promote and demote thresholds and the migration budget. The threshold gap is a hysteresis band, exactly as in 11.1's pressure FSM.

OS/runtime engineer. Owns what actually initiates migration and how deferred accesses are absorbed. This chapter provides the mechanism and stops short of the policy.

Performance engineer. Owns the placement equation and the churn counter, and must resist attributing to the tiers what is actually a shared-queue problem.

Silicon validation. Owns the deliberate-tie test and the both-tiers-simultaneously benchmark — neither of which arises naturally.

What each needs from the others: the ratio depends on a measured hot set; the thresholds depend on the migration cost RTL can report; the placement policy depends on hotness that saturates and decays. A gap in any one makes the loop unstable rather than merely suboptimal.

22. Common Misconceptions

BeliefCorrection
A page's tier can be derived from its addressOnly until the first migration
A migrating page can be read from its old copyIt has no authoritative home until the copy completes
Hotness is a count of accessesIt is a recent rate; without decay it describes the past
An unsaturated counter is merely impreciseIt invalidates the scale, then wraps and inverts the policy
More migration means better placementIt usually means the policy is fighting itself
Local memory should be as large as possibleBeyond the hot set it holds cold pages at the highest price
Expansion adds capacity, not bandwidthIt adds a second path — unless a shared queue serialises them
Access counts show whether placement is goodOnly churn distinguishes good placement from thrash

23. Interview Reasoning

24. Exercises

  1. Calculation. A workload has a 1 TB footprint and a measured 180 GB hot set. Local memory is 256 GB. Compute hot pages resident, hot pages remote, and wasted local capacity. Then recompute for a local size of 128 GB and state which configuration you would ship and what it costs.

  2. Analysis. A tiered server shows 30% of accesses hitting expanded memory and stable throughput. Explain why this is insufficient to conclude that placement is good, name the counter that settles it, and state what value would indicate a policy fighting itself.

  3. RTL task. Extend hotness_counter to use a two-level scheme: a small saturating counter per page plus a coarse counter per region. State the area saving at realistic page counts and what precision is lost, and identify which of this chapter's invariants the coarse level can no longer enforce.

  4. Assertion task. Write the property that proves the placement table is never repointed before a copy completes. Explain why the completion flag cannot be read directly in that property, and what the correct formulation is.

  5. Performance calculation. Local access is 80 ns and expanded is 250 ns. A migration costs 8 copy cycles at 1 GHz plus 4 deferred accesses. Compute the number of subsequent accesses needed for a promotion to pay for itself, and express that as a hotness threshold on a 0–15 scale with a decay interval of 16 cycles.

  6. Testbench design. Design the stimulus that distinguishes a > tie-break from a >= one in the hottest-page scan. Explain why a random access pattern will essentially never distinguish them, and what the minimum deliberate stimulus is.

  7. Debug task. A tiered server develops wrong-tier routing only after several hours of uptime, and rebooting fixes it temporarily. Give your investigation order, the two defects in this chapter that both produce that signature, and the single test that separates them.

  8. Design review. A colleague proposes removing the migration cooldown, arguing that the promote and demote thresholds are far enough apart to prevent oscillation on their own. Give the strongest version of that argument, state the workload shape that defeats it, and describe the counter that would show it happening.

25. Summary

A tiered server places pages, and placement is a control loop.

  • The tier is state, not a function of the address. An address-derived tier is correct until the first migration and wrong forever after — and every boot-time test passes.
  • A page in motion has no home. Accesses must be deferred; the measured trace deferred four, which is the visible price of atomicity.
  • Hotness must saturate and decay. Without saturation it exceeded its declared maximum at 18 of 15 and eventually inverts the policy; without decay it describes a workload phase that has ended.
  • Ties must break deterministically, or a one-character >= concentrates every migration decision at one end of the page space.
  • Migration must be atomic and rate limited. The ungoverned policy moved a page ten times as often for the same end state, spending workload bandwidth on movement.
  • Size local memory to the hot set. Below it, hot pages go remote — 64 GB in the measured case. Above it, the most expensive memory in the machine holds cold pages.
  • Two tiers are two bandwidths — 40 against 32, a 25% uplift — unless a shared queue serialises them, in which case the expanded tier gets nothing.
  • Churn, not access counts, distinguishes good placement from thrash.
  • Verification: 25 of 25 mutations killed, 45 assertions. The baseline caught a real RTL defect — a torn-page checker that read the completion flag on the edge that sets it, firing on correct behaviour — plus a testbench asserting a wrap that could not occur and a serialisation test in which nothing contended.

Next: 11.5 — AI Workloads on Expanded Memory, which takes a workload class whose access pattern contests almost every assumption this chapter relies on.

Continue learning

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.