Before running the compiler, predict the cycle count for this function with -O0 and with -O2:
int dot8(int8_t *a, int8_t *b, int n) {
int sum = 0;
for (int i = 0; i < n; i++)
sum += (int)a[i] * (int)b[i];
return sum;
}
With n = 16 on your RV32I core (no M extension, no cache):
-O0 |
-O2 |
Ratio | |
|---|---|---|---|
| Your prediction (cycles) | |||
Measured with rdcycle |
Think through:
-O0, how many instructions does one loop iteration generate? (Hint: load, sign-extend cast, multiply via mul-absent fallback, add, increment, branch — count them.)-O2, which instructions does the compiler eliminate or combine?M extension (mul instruction): how many cycles would i * j cost?After Lab 3, you will fill in the "Measured" row. Keep your prediction — comparing it to the measurement is more valuable than the number itself.
A useful mental model: performance is bounded by either compute or memory bandwidth.
A dot product reuses nothing — arithmetic intensity ≈ 0.5 MACs/byte. A matrix multiply reuses rows and columns — intensity = O(N). We will revisit this in Module 5 when designing the accelerator.
-O0 vs. -O2 on the boardGoal: measure the cycle count of a multiply loop on your Tang Nano 9K running Project 1.
// Compile twice: once with -O0, once with -O2
int result = 0;
uint32_t t0 = read_cycle();
for (int i = 0; i < 64; i++)
result += (int8_t)a[i] * (int8_t)b[i];
uint32_t t1 = read_cycle();
// Store (t1-t0) in x10 (a0), then ebreak
// Read x10 from your testbench or from LEDs
Report:
-O0 (no optimization).-O2.M extension (mul instruction) and report the speedup.Module 3 — HW/SW Interfaces: once you can run C programs on your core, the next question is how software talks to hardware peripherals — memory-mapped I/O, a minimal on-chip bus, and Zmmul + CMAC as examples of ISA extension and custom instruction. Project 2 begins.