Counter Wraparound Visualizer
Run the Counter Wraparound Visualizer MicroSim Fullscreen
You can include this MicroSim on your website using the following iframe:
1 2 | |
About This MicroSim
The Cortex-M cycle counter, CYCCNT, is 32 bits. At 150 MHz it fills and rolls over to zero every 28.6 seconds. That is not a rare event — it is guaranteed to happen during any benchmark you run for more than half a minute.
The counter is not a line from 0 to 4,294,967,295. It is a circle, and this
dial makes that literal. When your measurement straddles the top of the circle,
end - start is negative.
The sim uses a 10-bit demo counter (0 to 1023) so the wrap is visible, but the arithmetic is identical.
The Fix Is One Bitwise AND
1 | |
At the defaults — start 950, end 50 — naive subtraction gives -900, which is not a duration. Masked subtraction gives 124, which is correct: 74 counts to reach the wrap, then 50 more.
Why the Mask Works
This is the part worth understanding rather than memorizing.
The counter's range is a power of two. When it wraps, it does not lose
information — it discards exactly the bit that overflowed past bit 31. The
subtraction end - start produces a borrow out of the same position. Masking
with 0xFFFFFFFF discards that borrow, which cancels the wrap precisely.
This is why the demo uses 1024 and & 0x3FF rather than some round decimal
number. If the counter counted 0 to 999 and reset, no bitmask would fix it and
you would need a modulo instead. The trick works because of binary, not because
of arithmetic in general.
In C with uint32_t variables the mask is implicit — unsigned subtraction
already wraps correctly. In Python, where integers are arbitrary precision, you
must write the mask explicitly or you will get the negative number.
How to Use
- At the defaults, compare the two panels. Confirm 1024 − 950 + 50 = 124 by hand.
- Drag End value above the start, say to 990. No wrap occurs, and both panels now agree — the naive answer is right by luck.
- Drag it back below the start. The naive panel goes red again.
- Watch the green arc on the dial. It always shows the true elapsed span, clockwise from start to end, and its length always matches the masked result.
Lesson Plan
Grade Level
Undergraduate (college junior/senior)
Duration
10-12 minutes
Prerequisites
- Binary representation and bitwise AND
- A hardware counter increments and rolls over
Learning Objective
Students will be able to apply the masked-subtraction formula to compute elapsed cycles across a wraparound, and demonstrate why naive subtraction fails.
Activities
- Hand-verify (4 min): For three start/end pairs, students compute elapsed cycles by hand and check both panels.
- Find the safe case (3 min): Students identify when naive subtraction happens to work and explain why relying on it is still wrong.
- Language check (4 min): Students explain why C with
uint32_tneeds no explicit mask but Python does.
Assessment
Ask: "Your benchmark reports an elapsed time of -12,000 cycles. What happened, and what is the actual elapsed count if the counter is 32 bits?"
Related Resources
References
- Data Watchpoint and Trace unit — the CYCCNT register's definition.
- Modular arithmetic — the general framework; masking is the power-of-two special case.