A microarchitecture review is the moment when a design is checked by people who did not build it, and a checklist is what stops a review from relying on memory. Most serious bugs and missed targets fall into known categories: a full queue nobody handled, a reset value nobody set, a flush that leaves something behind. This article gathers the questions from across this tutorial into one practical list, organized by block, with an explanation of why each question matters and how to run a review.
11 min read | Intermediate
What You'll Learn
- Run a microarchitecture review with a clear structure
- Check a pipeline, a cache and a memory interface for common omissions
- Review traps, power, reset and debug support
- Record decisions and follow up on them
Why Use a Checklist
Reviewers are skilled, but they are human, and a long meeting wears down attention. A checklist makes sure the dull questions get asked. Those are often the ones that matter: nobody finds "what is the reset value?" exciting, but missing reset values have stopped many chips from booting.
Use this list for a design review, for a spec review, or as your own check before showing your work to anybody. Not every question applies to every design. A small core has no reorder buffer, and an embedded core may have no MMU. Skip what doesn't apply, and add what your project has learned.
Running a Review
A good review has some structure:
- Send material ahead. Reviewers should read the spec before the meeting.
- Invite the right people. An architect, an RTL designer from a neighboring block, a verification engineer, a physical designer, and for some blocks a software engineer.
- Start with the goals. What must this block achieve, and how do we know?
- Walk through the normal flow, then the corners. Spend most of the time on the corners.
- Record actions, with an owner and a date. A review with no list of actions was only a presentation.
Keep it focused on the design, not on the designer. The aim is for everyone to find problems while they are cheap to fix.
Goals and Requirements
- Are performance, power, area and frequency targets written down, with the workloads and conditions?
- Is each target backed by a model, or by measurement? Performance Modeling explains how.
- What's the margin on each budget?
- What is out of scope, and does everybody agree?
- Which assumptions could change, and what would be affected?
Pipeline
- Is there a table of what each stage does and what each pipeline register holds?
- Is each data dependence handled by forwarding or a stall, for every distance and operand, including store data?
- Does forwarding exclude x0, check the write enable, and pick the newest value?
- Is the load-use case detected exactly, with no false stalls on instructions with no source registers?
- If stall, flush and freeze occur together, is the priority defined?
- Does a flush clear every side effect, including counters and any state update?
- Does a value being forwarded survive a pipeline freeze?
- Which is the critical path, and is there a plan for it?
Data Hazards and Forwarding and Load-Use Stalls and Control Hazards explain each of these points.
Front End
- What happens on a BTB or predictor miss, and on a false hit?
- Is the predictor read within one cycle? If not, what is lost on each taken branch?
- Are history and the return stack repaired after a flush?
- What's the misprediction penalty, and is it verified?
- Does fetch handle an instruction that crosses a line or a page?
- What happens if a fetch error occurs on a wrong path? It must not trap.
Memory System
- Are cache size, ways, line size and policies stated, along with the hit latency?
- Do valid bits clear at reset, and how does cache invalidation at start-up happen?
- Is a dirty victim always written back, including during a flush?
- Does each load check the store buffer, handling partial overlaps?
- What happens when each queue fills: store buffer, miss queue, write buffer?
- Are device regions non-cacheable, and non-speculative?
- Is the memory ordering model stated, and are fences implemented?
- How do DMA and coherence work? Who cleans the caches?
- What happens on a bus error, on a read, on a write and on an instruction fetch?
- What protects memories against soft errors: parity, ECC, or nothing?
The questions on full queues are the classic gap. A design with only a normal path often hangs when a store buffer fills up while a load waits for it, in a pattern no one drew on the whiteboard. Look for deadlock: a cycle of things all waiting for each other.
Virtual Memory
- Are TLB sizes, associativity and replacement stated?
- Is the walker's behavior defined on a fault at each level?
- Does the hardware set A and D bits, or does it raise a fault?
- How does
sfence.vmawork, with and without an address and ASID? - Do cache index bits fit within the page offset, or how are aliases handled? Caches and Virtual Memory explains.
- Does a misaligned access crossing a page handle a fault on the second page?
Quick Check
Q: A store buffer with 4 entries is full, and the oldest entry waits for a line that is being evicted to make room for a load's miss, and that eviction waits for the store buffer. What is this, and how would a review spot it?
Show Answer
A deadlock: a cycle of waits. A review finds it by listing each resource, what it waits for, and asking if a cycle can form. Random stress testing and formal checks catch it too, but finding it in a review costs the least.
Traps and Privilege
- Is each exception cause listed, with its priority and with what goes in
mtval? - Are exceptions precise, in every case?
- Is it clear which stage takes a trap, and how interrupts are attached to an instruction?
- What's the worst-case interrupt latency, and what makes it worse?
- Can a long operation be interrupted?
- Are CSR side effects handled, by a flush after writes that change behavior?
- Are illegal encodings detected, including illegal CSR accesses?
- Does
wfiwake correctly with interrupts disabled? Interrupts and Interrupt Latency covers it.
Reset and Clocks
- Does every state element have a defined reset value, or a reason not to?
- Is reset release synchronized to the clock?
- Which memories are unknown after reset, and who initializes them?
- What's the first instruction address, and how is it set?
- Are clock domain crossings listed and synchronized? Clocks and Resets in a System covers these.
In simulation, unknown values can hide reset bugs, because some tools turn unknown values into known ones. Run a test with random initial values for all uninitialized state.
Power
- Which clocks are gated, and is the design tested with gating on?
- What power states exist, and what state is lost in each?
- What wakes the core, and how long does it take?
- Are wide structures idle when they aren't in use?
- Are power estimates based on realistic activity, rather than a guess?
Debug and Observability
- Can a debugger halt the core, read registers and set breakpoints?
- Are there enough performance counters for the events needed to analyze silicon?
- Can a hung core be diagnosed, and is there visibility into its queues?
- Is there an instruction trace?
- If something fails after tape-out, what could be changed by software, and is there any way to turn a feature off?
That last point is often worth a small amount of logic. A bit in a CSR that disables a new prefetcher or predictor can turn a fatal bug into a small loss of performance. Such chicken bits have saved many chips.
Where Does This Matter?
Companies keep their own lists, grown from past failures. Each bug that escapes to silicon gets a root-cause study, and an item on the list so that it can't happen again. After a few product generations, the checklist holds years of hard-won experience, which is one of the most valuable things an engineering team owns. New engineers can learn a lot just by reading through it and asking why each item is there.
Verification
- Does each requirement in the spec link to a test or an assertion?
- Is there a reference model and a commit-trace comparison?
- Do tests randomize memory latency and interrupts?
- Are functional coverage goals agreed, and on track?
- Which logic is suited to formal proof?
- Has a real operating system been booted, on an emulator or an FPGA?
- Are performance regressions run?
Verifying a CPU explains these methods.
Security
- Can user code reach any privileged state or any secret?
- Do predictors and caches leak information across privilege or process boundaries?
- Can speculative accesses reach protected memory?
- Are CSR fields safe against unusual values?
- Is debug access locked down in production?
Software and Toolchain
- Is the compiler's scheduling model updated for this pipeline?
- Are instruction latencies and restrictions documented?
- Does the ISA string in the build match what the hardware provides?
- Are optional extensions reported correctly in
misa? - Is there a plan to handle errata in software?
Quick Check
Q: A team is adding a new prefetcher late in the project. Which review item reduces the risk the most, for the least cost?
Show Answer
A chicken bit: a CSR field that turns the prefetcher off. If it has a bug in silicon, the product can still ship with a small loss in performance, rather than needing a new mask set.
After the Review
A review only helps if its results are acted on. Write down each action with an owner and a date, and track them to closure. Record decisions and the reasons for them, so that the same discussion doesn't happen again. Then update the checklist itself: if the review found a new kind of problem, add it. After tape-out and bring-up, compare what happened with what the reviews said, and feed the lessons into the next project.
Common Mistakes
Mistake #1: Reviewing too late
Once the RTL is complete, reviewers are reluctant to suggest big changes, and designers are reluctant to accept them. Review the spec and block diagrams early.
Mistake #2: Spending the meeting on the normal flow
The designer knows the normal flow well. Spend the time on full queues, errors, resets and simultaneous events.
Mistake #3: Treating the checklist as finished
A list that never grows stops finding bugs. Add an item for each bug that escapes, and remove what no longer applies.
Practice Exercise
Challenge: Review This Design
A colleague proposes this store buffer: "A 2-entry store buffer sits after the cache tag check. Stores enter after commit and write the data array when no load is using it. Loads read the data array only." Using the checklist, find at least four problems or missing facts.
Hint
Think about a load right after a store, what happens when the buffer is full, and what happens on an error or a reset.
Solution
(1) Loads don't check the buffer, so a load right after a store to the same address reads stale data. It needs store-to-load forwarding, or a stall. (2) "When no load is using it" could starve the buffer forever under a stream of loads, so a store needs a way to win after waiting. (3) It doesn't say what happens when the buffer is full. It should stall commit, and that should be stated. (4) Nothing is said of a fence or of memory ordering: must the buffer drain for fence? (5) Device stores must not be merged or reordered. (6) It doesn't say what happens to a buffered store on reset, or on a bus or parity error, after the instruction has already committed.
Summary
- A checklist makes sure that the dull but important questions get asked.
- Review goals first, then walk the normal flow quickly and the corner cases slowly.
- Check every full queue, flush, reset value and error path, and look for cycles of waiting.
- Plan for failure: chicken bits, counters and debug visibility can save a chip.
- Record actions, follow them up, and add each escaped bug to the list.