Module 2 Exercises — ISA & Microarchitecture

Back to the Course 3 syllabus. Read first: H&H 6–8 (App. B as reference); skim Yiu 4, 5.1–5.6, 6.1–6.6 for the M-profile contrast.

Work in course3/m2/ of the labs repo. Timing exercises use a small C harness (clock_gettime/mach_absolute_time) around assembly or C kernels — harness scaffolding is part of the exercise setup; keep kernels and harness in separate files.

NoteExercises in this set
TipBenchmarking discipline (used from here through Module 5)

Pin expectations before running anything: median of ≥10 runs, report min/median, note that P-cores vs. E-cores can move results (macOS decides scheduling; long-running hot loops generally land on P-cores). Record chip model and macOS version in notes.md once per module.

Paper exercises

Exercise 2.1 — H&H problem sets. Work select exercises from H&H Ch 6 (assembly ↔︎ machine-code translation, addressing modes), Ch 7 (datapath analysis: which stages, what forwarding, cycle counts through the pipelined design), and Ch 8 (cache mapping/AMAT computations, virtual-address translation walks).

Exercise 2.2 — Three dialects, one routine. Take a 5-line routine (e.g., absolute value of a sum) and write it three times on paper: A32 (H&H App. B style, with its condition-code-on-everything flavor), A64 (what you actually run), and T32/Thumb-2 (Yiu 5’s UAL). In notes.md, tabulate: instruction count, encoding widths (fixed 32 vs. mixed 16/32), register count visible, and which dialect had to spend extra instructions where. This table gets revisited in Module 6.

Machine exercises — measuring the microarchitecture

Exercise 2.3 — Compiler forensics. Write ~15 lines of C (a small loop with a helper function call), compile at -O0 and -O2, and disassemble both. Annotate side by side in notes.md: where did the locals go (stack vs. registers), what happened to the helper (inlined?), what happened to the loop (unrolled? strength-reduced?). H&H 6.5’s compile/assemble/link story, observed in the wild.

Exercise 2.4 — Cache-latency ladder. The pointer-chase: allocate an array of N pointers arranged in a random cycle, then time p = *p over millions of dependent loads, for N spanning ~16 KB → ~128 MB. Plot ns/load vs. working-set size and read the levels off the plateaus. Predict first from public M-series cache specs; reconcile in notes.md (H&H 8.3’s AMAT, live).

Working set Predicted regime Measured ns/load
16 KB L1
256 KB
4 MB
64 MB DRAM

Exercise 2.5 — Branch predictor experiment. Time the classic: summing elements greater than a threshold over (a) sorted and (b) shuffled data of the same values, with the comparison as a branch; then repeat with a branchless CSEL version. Explain all four numbers with H&H 7.5’s pipeline-flush cost model, and estimate the misprediction penalty in cycles from your own measurements.

Exercise 2.6 — ILP probe. Two loops of equal instruction count: one long dependent chain of ADDs (each result feeds the next), one with 8 independent accumulator chains interleaved. Time both; the throughput ratio approximates how much instruction-level parallelism the core exploits (H&H 7.7). In notes.md, connect the result to why the M-series is fast at the same clock as much simpler cores — and why none of this exists on the in-order Cortex-M4.