RISC-V Microarchitectural Design-Space Exploration in Chipyard

Overview

ECE 5504 — Computer Architecture · Virginia Tech · Fall 2024

Team project with Alok Mehendale and Benjamin Rice. Benchmarks were divided between us: Alok took rsort and vvadd, Benjamin took towers and median, and I took FFT and SHA-256. Results were combined for the final report.


Problem

General-purpose processor configurations are a compromise. Given an open, parameterised SoC generator, how much performance can be recovered by tailoring the microarchitecture to a specific workload — and where does that tailoring stop paying off?

We used Chipyard, the open-source RISC-V SoC framework, comparing the in-order Rocket core against the out-of-order BOOM core, and tuned SoC parameters per benchmark. The primary metric was cycles per instruction (CPI).

Design space explored

Configuration knobs varied across runs:

CategoryParameters
CacheWithL1DCacheSets, WithL1DCacheWays, WithInclusiveCache (L2), L1 prefetcher, cache size up to 128 KB
Replacement policyTrueLRU, PseudoLRU
Branch predictionWithTAGELBPD (TAGE-L), Alpha predictor
CoreWithNSmallBooms, WithNBoomPerfCounters, ROB entries, issue width, register file size

Six benchmarks were chosen to span different access patterns: median, towers, vvadd, rsort, FFT, and SHA-256.

My benchmarks

2D FFT

A memory-efficient 2D Fast Fourier Transform — Cooley-Tukey applied row-wise then column-wise over a 32×32 complex matrix, with temporary buffers used to improve locality during the column pass.

Because the workload is memory-bound with a predictable access pattern, the memory hierarchy dominated. Adding an L2 cache produced a 1.88× speedup over baseline. Prefetching improved latency further when combined with non-blocking memory. On the core side, I raised the floating-point register file to 128 entries, increased ROB entries to 64, and widened issue.

LRU was selected as the replacement policy — the other policies tested were equal or worse.

SHA-256

A FIPS 180-4 implementation processing input in 512-bit blocks through message padding, schedule expansion, and compression.

This one resisted optimisation. A modified TAGE predictor on the SmallBOOM configuration gave a slight improvement over the other BOOM configs, achieved by raising the integer register file to 128 and ROB entries to 64 — but the gain was marginal. The compression function is a tight dependent chain of bitwise operations with a small working set, so there is little for a larger cache or a better predictor to exploit.

The negative result is the useful one: not every workload has microarchitectural headroom, and cryptographic hashing is a case where throwing hardware at the problem does close to nothing.

Team results, for context

The other benchmarks showed the same pattern of workload-specific sensitivity. Median improved from a CPI of 2.043 to 1.516 — a 1.348× speedup — through an L2 cache, an L1 prefetcher, and a replacement policy, though some branch predictors made it worse given the program's simplicity. Towers, being heavily recursive, achieved its best CPI of 1.004 from a TAGE predictor alone; the fully modified configuration was slower, because the extra components added overhead without benefit.

Takeaway

The project's conclusion was that processor design is an exercise in balance: general-purpose features carry you most of the way, workload-specific tuning recovers the rest, and knowing which components to remove matters as much as knowing which to add.

For me the useful part was hands-on exposure to a real SoC generator — editing Rocket and BOOM configurations in Scala, running full simulations, and reading CPI results back against a hypothesis about a benchmark's memory behaviour.

Artifacts

Project code lives in a Virginia Tech GitLab repository. The final report is available on request.