This is a worked-examples deep dive for Superscalar execution . The parent note derived one master formula for how many instructions a superscalar core finishes each clock tick. Here we throw every kind of input at that formula until you can spot the bottleneck by eye.
Before we compute anything, let us re-earn every symbol, because a smart 12-year-old should be able to read from line one.
Definition The words behind the symbols
Cycle — one tick of the CPU clock, the smallest unit of time the processor knows.
Instruction — one command, like "add these two numbers".
IPC (Instructions Per Cycle) — how many instructions finish in one tick. Bigger is faster. If IPC = 4, four commands complete every tick.
==Issue width W == — the widest the front of the machine can go: the most instructions it can fetch/decode in one tick. Think of it as the number of doors at the entrance.
Functional unit — a small machine that does one job: an adder (ALU), a multiplier, a memory unit (load/store), a branch checker. If you have 3 adders you can do 3 adds at once.
F i — how many units of type i you own (e.g. F mem = 2 means two memory units).
p i — the fraction of the program that needs unit type i . If 30% of instructions touch memory, p mem = 0.3 . All the p i add up to 1.
ROB (Reorder Buffer ) — a waiting room that holds instructions "in flight". Its size is the biggest crowd the machine can look through to find independent work.
D — average dependency chain length : how many instructions are stacked in a line, each waiting on the one before it (a RAW chain).
L — average latency : how many ticks one instruction takes from start to result.
Why min and not a sum or average? Because a chain is only as strong as its weakest link — the machine can never go faster than its tightest constraint, so the smallest of the three numbers is the real speed. That is the whole idea; every example below just asks which gate is smallest .
Look at the three gates above. An instruction stream (the arrows) can be squeezed by any one of them. The red gate in each example is the one that actually limits us — that is what we are hunting for.
Every superscalar-IPC problem falls into one of these cells. The examples that follow are labelled with the cell they hit, and together they cover all of them .
#
Case class
What is special
Which gate usually wins
Example
A
Front-end bound
plenty of units, small W
gate 1 (W )
Ex 1
B
Execution bound (memory)
one unit type overloaded
gate 2
Ex 2
C
Execution bound (compute)
different unit type overloaded
gate 2
Ex 3
D
Dependency bound
long chain, tiny ROB
gate 3
Ex 4
E
Degenerate: p i = 0
a unit type unused (divide-by-zero risk)
ignore that unit
Ex 5
F
Degenerate: D = 1 or L = 1
no chains / instant results
gate 3 blows up (∞)
Ex 5
G
Tie / two gates equal
boundary case
either
Ex 6
H
Real-world word problem
you must build p i from counts
any
Ex 7
I
Exam twist: "what to fix?"
find gate, then improve it
reasoning
Ex 8
J
Limiting behaviour
W → ∞ or ROB→ ∞
remaining gate
Ex 9
Worked example Example 1 — Cell A: front-end bound
Given: W = 4 ; 3 int ALUs, 2 FP, 2 mem, 1 branch. Mix: 40% int, 20% FP, 30% mem, 10% branch. D = 3 , ROB= 128 , L = 2 .
Forecast: guess now — is the entrance or the machinery the bottleneck?
Gate 1 (front-end): W = 4 .
Why this step? It is the hard ceiling: you can never finish more than you let in.
Gate 2 (execution): compute F i / p i for each type and keep the smallest.
int: 3/0.4 = 7.5
FP: 2/0.2 = 10
mem: 2/0.3 = 6.67
branch: 1/0.1 = 10
Why this step? The busiest unit relative to demand throttles everyone, so we take min = 6.67 .
Gate 3 (dependency): 3 × 2 4 × 128 = 6 512 = 85.3 .
Why this step? A big ROB (128) easily hides short chains (D = 3 ), so this gate is wide open.
Combine: IPC = min ( 4 , 6.67 , 85.3 ) = 4 .
Verify: the answer equals W exactly, and both other gates (6.67 , 85.3 ) exceed it — consistent with "front-end bound". Units: instructions/cycle. ✓ A wider machine (bigger W ) is the only thing that would help.
Worked example Example 2 — Cell B: memory-bound execution
Given: same hardware as Ex 1, but mix = 30% int, 0% FP, 60% mem, 10% branch.
Forecast: 60% of work hits only 2 memory units — will they cope?
Gate 1: W = 4 .
Gate 2:
int: 3/0.3 = 10
mem: 2/0.6 = 3.33 ← smallest
branch: 1/0.1 = 10
Why this step? Memory demand (0.6) is huge but supply (2 units) is fixed, so mem chokes.
Gate 3: 3 × 2 4 × 128 = 85.3 — still wide open.
Combine: IPC = min ( 4 , 3.33 , 85.3 ) = 3.33 .
Verify: 3.33 < W = 4 , so the machine cannot even use its full width — correct signature of execution-bound. Sanity: 2 mem units can do 2 mem ops/cycle; if 60% of a stream of IPC instructions are mem, then 0.6 ⋅ IPC ≤ 2 ⇒ IPC ≤ 3.33 . ✓
Worked example Example 3 — Cell C: compute-bound (different unit type)
Given: W = 6 ; 2 int ALUs, 1 FP, 4 mem, 2 branch. Mix: 50% FP, 20% int, 20% mem, 10% branch. D = 4 , ROB= 64 , L = 3 .
Forecast: heavy FP program, only one FP unit — trouble?
Gate 1: W = 6 .
Gate 2:
FP: 1/0.5 = 2.0 ← smallest
int: 2/0.2 = 10
mem: 4/0.2 = 20
branch: 2/0.1 = 20
Why this step? Half the instructions want the single FP unit; that unit does 1/cycle, so 0.5 ⋅ IPC ≤ 1 .
Gate 3: 4 × 3 6 × 64 = 12 384 = 32 .
Combine: IPC = min ( 6 , 2 , 32 ) = 2 .
Verify: FP throughput = F F P / p F P = 2 , and 2 is the minimum — compute-bound on FP. Adding FP units is the fix. ✓
Worked example Example 4 — Cell D: dependency-bound (long chain, tiny ROB)
Given: W = 4 ; units plentiful (int 6 , FP 3 , mem 3 ). Mix: 60% int, 20% FP, 20% mem. But D = 8 , ROB= 8 , L = 4 .
Forecast: the machinery is huge — but the waiting room is tiny and the chains are long. Watch gate 3.
Gate 1: W = 4 .
Gate 2:
int: 6/0.6 = 10
FP: 3/0.2 = 15
mem: 3/0.2 = 15
→ min = 10 .
Gate 3: 8 × 4 4 × 8 = 32 32 = 1.0 ← smallest.
Why this step? Small ROB (8) cannot look past the long chain (8) to find independent work, and each link takes 4 cycles.
Combine: IPC = min ( 4 , 10 , 1.0 ) = 1.0 .
Verify: 1.0 < W and 1.0 < every F i / p i , so the only limiter is dependencies — cell D exactly. Fix: bigger ROB (window) or shorter chains (better renaming / scheduling). ✓
Worked example Example 5 — Cells E and F: degenerate inputs
Given: W = 4 ; int 4 , FP 2 , mem 2 . Mix: 70% int, 0% FP , 30% mem (no floating point at all!). D = 1 , ROB= 128 , L = 1 .
Forecast: what happens to the FP term F F P / p F P when p F P = 0 ? And to gate 3 when D = 1 , L = 1 ?
Handle p F P = 0 (Cell E): the term 0 2 is undefined , but its meaning is "FP can never limit us because no instruction wants it" → treat as + ∞ and drop it from the min .
Why this step? A unit no one uses can never be a bottleneck; a divide-by-zero here is a modelling artefact, not a real limit.
Gate 2 (over used types only):
int: 4/0.7 = 5.71
mem: 2/0.3 = 6.67
→ min = 5.71 .
Gate 3 with D = 1 , L = 1 (Cell F): 1 × 1 4 × 128 = 512 .
Why this step? D = 1 means no chains (every instruction independent) and L = 1 means instant results — dependencies impose essentially no limit, so this gate is enormous.
Combine: IPC = min ( 4 , 5.71 , 512 ) = 4 .
Verify: with p F P = 0 correctly excluded, the front-end W = 4 wins. Had we wrongly plugged 2/0 = ∞ into the min it would still give 4 — but the reasoning (drop unused units) is what an exam wants. ✓
p i = 0 trap
Never compute F i / p i for a unit no program instruction uses. It is a division by zero. Its real value is "∞ / not a bottleneck" — skip that unit entirely .
Worked example Example 6 — Cell G: exact tie between two gates
Given: W = 4 ; int 4 , mem 2 . Mix: 50% int, 50% mem. D = 2 , ROB= 32 , L = 2 .
Forecast: compute both gates 1 and 2 — do they land on the same number?
Gate 1: W = 4 .
Gate 2:
int: 4/0.5 = 8
mem: 2/0.5 = 4 ← min = 4 .
Gate 3: 2 × 2 4 × 32 = 4 128 = 32 .
Combine: IPC = min ( 4 , 4 , 32 ) = 4 .
Verify: front-end and memory gates are both exactly 4 — a perfectly balanced design at width 4. Widening and adding a mem unit are both needed to improve, because relieving one gate leaves the other still at 4. ✓ This is the "balanced machine" boundary case designers aim for.
Worked example Example 7 — Cell H: real-world word problem (build
p i yourself)
Given: A trace of 1000 instructions : 500 integer, 150 floating-point, 250 loads/stores, 100 branches. Machine: W = 6 ; 4 int, 2 FP, 2 mem, 1 branch. D = 3 , ROB= 96 , L = 2 .
Forecast: first convert counts to fractions, then find the gate.
Build the mix: divide each count by 1000.
p int = 0.5 , p F P = 0.15 , p mem = 0.25 , p br = 0.10 .
Why this step? The formula needs fractions , not raw counts; they must sum to 1 (they do: 0.5 + 0.15 + 0.25 + 0.10 = 1 ).
Gate 1: W = 6 .
Gate 2:
int: 4/0.5 = 8
FP: 2/0.15 = 13.33
mem: 2/0.25 = 8
branch: 1/0.10 = 10
→ min = 8 .
Gate 3: 3 × 2 6 × 96 = 6 576 = 96 .
Combine: IPC = min ( 6 , 8 , 96 ) = 6 .
Verify: fractions sum to 1 ✓; the front-end (W = 6 ) is the tightest gate. So this workload is front-end bound on this machine — you would need a wider decoder to go faster, not more execution units. ✓
Worked example Example 8 — Cell I: exam twist "what should we fix?"
Given: W = 4 ; int 3 , FP 1 , mem 3 , branch 1 . Mix: 30% int, 40% FP, 20% mem, 10% branch. D = 3 , ROB= 128 , L = 2 . Question: name the bottleneck and the single cheapest fix.
Forecast: which gate is smallest, and which knob relieves it?
Gate 1: W = 4 .
Gate 2:
int: 3/0.3 = 10
FP: 1/0.4 = 2.5 ← min
mem: 3/0.2 = 15
branch: 1/0.1 = 10
Gate 3: 3 × 2 4 × 128 = 85.3 .
Combine: IPC = min ( 4 , 2.5 , 85.3 ) = 2.5 .
Diagnose the fix: the limiter is FP (F F P / p F P = 2.5 ). Add one FP unit → new FP gate 2/0.4 = 5 , so the new IPC = min ( 4 , 5 , 85.3 ) = 4 .
Why this step? Improving anything other than FP (e.g. adding mem units) leaves FP at 2.5 and changes nothing — you must relieve the actual smallest gate.
Verify: before-fix IPC = 2.5 ; after adding one FP unit IPC = 4.0 (now front-end bound). One unit bought a 60% speedup — the correct, targeted fix. ✓
Worked example Example 9 — Cell J: limiting behaviour (
W → ∞ , ROB→ ∞ )
Given: Take Ex 2's hardware/mix (mem-bound, 60% mem, 2 mem units) but imagine an infinitely wide front-end (W → ∞ ) and an infinite ROB .
Forecast: with the front-end gate and dependency gate both removed, what stops us?
Gate 1 (W → ∞ ): removed, no longer in the min.
Gate 3 (ROB→ ∞ ): D L W ⋅ ROB → ∞ : removed too.
Only gate 2 survives: mem = 2/0.6 = 3.33 .
Why this step? Even with an infinite machine, only 2 memory units exist; 60% of instructions need them, so 0.6 ⋅ IPC ≤ 2 .
Combine: IPC = min ( ∞ , 3.33 , ∞ ) = 3.33 .
Verify: the physical execution resource is the ultimate ceiling — you cannot out-fetch a hardware shortage. Matches Ex 2's answer exactly (3.33), confirming that memory was the real limiter there, not the width. ✓
Recall Quick self-test
Front-end bound means IPC equals which symbol? ::: W (the issue width)
If p i = 0 for some unit type, what do you do with its F i / p i term? ::: Drop it — an unused unit can never bottleneck; the ratio is undefined (∞ ).
Which gate is D ⋅ L W ⋅ ROB ? ::: The dependency gate (gate 3); it shrinks with long chains D and high latency L , grows with a bigger ROB window.
In a balanced design, two gates are equal — why is that hard to improve? ::: Relieving one leaves the other at the same value, so you must improve both to gain speed.
A workload is 60% memory with 2 mem units. Hard ceiling on IPC? ::: 2/0.6 = 3.33 , no matter how wide the machine.
Mnemonic Three gates, slowest wins
W idth · U nits · W indow → "WUW : the whole machine only goes as fast as its weakest gate." Always compute all three, then take the min .
See also: Tomasulo's Algorithm , Branch Prediction , Cache Hierarchy , VLIW Architecture , Power-Performance Tradeoffs .