Hello! Welcome back to our series on embedded driver development.
In the last lesson, we examined the processor's internal state, covering the register set, execution modes, and privilege levels. We now have a solid understanding of what the processor tracks. This lesson shifts our focus to how the processor gets work done by executing instructions.
Today, we'll explore the ARM instruction pipeline and its impact on execution timing. This concept is fundamental to understanding modern processor performance. It explains why code doesn't always execute in a simple, predictable number of cycles and is a key factor in performance optimization and debugging. Given your background in functional safety, this lesson will also touch upon why these performance-enhancing features create significant challenges for predictable, real-time systems.
1. The Core Concept: An Assembly Line for Instructions
At its heart, pipelining is a technique to increase instruction throughput—the number of instructions completed per unit of time. It achieves this by overlapping the execution of multiple instructions, much like an assembly line in a factory.
To build an intuitive understanding of this, let's start with a video that uses a simple fast-food drive-through analogy.
Ep 085: Introduction to the CPU Pipeline
The video 'Introduction to the CPU Pipeline' from Intermation provides an excellent conceptual overview of pipelining.
Please watch from the beginning to 10:27. The first part (until 04:54) introduces the analogy. The second part applies this to a simple 3-stage CPU pipeline (Fetch, Decode, Execute) and compares the execution time for a sequence of instructions with and without pipelining.
As the video demonstrated, a simple pipeline breaks instruction processing into stages. For many ARM cores, especially simpler ones like the ARM7TDMI you might have encountered, a three-stage model is common:
- Fetch: The processor fetches an instruction from memory.
- Decode: The instruction is decoded to determine the required operation and operands.
- Execute: The operation is performed, and results are written back to registers.
With these stages, three different instructions can be processed simultaneously: one being executed, one being decoded, and one being fetched.
Throughput vs. Latency
It's crucial to distinguish between two key performance metrics:
- Instruction Latency: The total time it takes for a single instruction to complete its journey through all pipeline stages.
- Instruction Throughput: The rate at which instructions finish executing.
Pipelining does not reduce the latency of a single instruction. In fact, due to the overhead of pipeline registers between stages, it might slightly increase it. Its power lies in dramatically increasing throughput. In an ideal N-stage pipeline, once the pipe is full, an instruction can complete every clock cycle, leading to a theoretical speedup of nearly N times.
2. When the Assembly Line Breaks: Pipeline Hazards
The ideal scenario of one instruction completing per cycle is rarely achieved in practice. The flow can be disrupted by dependencies and resource conflicts between instructions. These disruptions are called pipeline hazards. Understanding them is key to understanding real-world execution timing.
Hazards fall into three main categories.
a) Structural Hazards
A structural hazard occurs when two or more instructions in the pipeline need the same hardware resource at the same time. For example, if a processor has a single, unified memory access unit, an instruction in the Execute stage trying to access data might conflict with an instruction in the Fetch stage trying to fetch the next instruction.
The solution is to stall the pipeline. One instruction is paused for a cycle, creating an empty slot—often called a pipeline bubble—that moves through the pipe.

Modern processors, including most ARM cores, mitigate structural hazards by having multiple execution units and dedicated memory paths (e.g., separate instruction and data buses), making these hazards less common.
b) Data Hazards
This is the most frequent type of hazard. It occurs when an instruction depends on the result of a previous instruction that has not yet completed.
Consider this simple sequence:
ADD R0, R1, R2 ; R0 = R1 + R2
SUB R3, R0, #10 ; R3 = R0 - 10
The SUB instruction needs the result of the ADD instruction, which is in R0. By the time the SUB instruction is in the Decode stage, the ADD is still in the Execute stage and hasn't written its result back to the register file.
A naive solution would be to stall the pipeline for several cycles until the ADD result is written back. However, a much more efficient hardware solution is used: forwarding (or bypassing).
Forwarding creates special data paths that take the result directly from the output of one pipeline stage (like the ALU in the Execute stage) and feed it into the input of an earlier stage (like the Decode stage) for the next instruction. This often eliminates the need for a stall entirely.
c) Control Hazards
Control hazards are caused by instructions that change the normal flow of execution, such as branches, function calls, and exceptions. The problem is that when the processor fetches a branch instruction, it doesn't know which instruction to fetch next until the branch condition is evaluated much later in the pipeline.
This next video focuses specifically on the problem of branch instructions.
Branch in a Pipeline - Georgia Tech - HPCA: Part 1
This clip from Udacity's 'High Performance Computer Architecture' course explains exactly what happens when a branch enters the pipeline.
Watch from 01:11 to 04:25. This segment details how a branch progresses through the stages, what happens on a correct prediction, and the penalty (pipeline flush) incurred on a misprediction.
As the video explains, the processor must deal with the uncertainty of a branch:
- Branch Prediction: The processor doesn't wait; it makes a guess about the branch outcome (e.g., "assume not taken") and begins speculatively fetching instructions from the predicted path.
- Correct Prediction: If the guess was correct, the pipeline continues without interruption. No performance is lost.
- Misprediction: If the guess was wrong, the speculatively fetched instructions are incorrect and must be discarded. This is called a pipeline flush. The pipeline then stalls while the correct instruction is fetched, incurring a significant performance penalty of several clock cycles.
The deeper the pipeline, the more instructions are fetched speculatively, and the higher the penalty for a misprediction. This is a critical trade-off in processor design.
Test your understanding!
You are optimizing a tight loop in C. The compiler generates assembly with a conditional branch at the end of the loop. To improve performance, a colleague suggests "unrolling the loop"—essentially duplicating the loop body a few times to reduce the number of branch instructions executed. Based on what you've learned about control hazards, why is this an effective optimization strategy?
Show answer
Loop unrolling is effective because it directly reduces the frequency of control hazards. Each conditional branch at the end of a loop presents a potential for a branch misprediction, which would cause a costly pipeline flush. By duplicating the loop body, you perform more work per iteration and execute the branch instruction less often. This minimizes the number of potential mispredictions and stalls, leading to a smoother flow of instructions through the pipeline and better overall performance, especially for loops that execute many times.
3. A Real-World ARM Pipeline: The Cortex-M7
Simple 3- or 5-stage pipelines are good for learning, but modern high-performance cores are more complex. Let's look at the pipeline of the ARM Cortex-M7, a powerful microcontroller core used in demanding automotive and industrial applications.

Don't worry about memorizing every detail. Focus on these key features:
- Superscalar / Dual-Issue: The Cortex-M7 can fetch, decode, and issue up to two instructions per clock cycle, as long as they don't have resource conflicts. This is a major source of its high performance.
- Multiple Execution "Pipes": Notice the parallel paths for different operations (ALU, MAC, Load/Store, Branch). This design heavily mitigates structural hazards, allowing different types of instructions to execute in parallel.
- In-Order Issue: While it can execute instructions in parallel, the Cortex-M7 is an "in-order" machine. It issues instructions to the execution units in the same order they appear in the program. (This contrasts with "out-of-order" execution found in Cortex-A processors, which we'll cover later in the course).
- Extensive Forwarding: The diagram explicitly mentions this. It's a testament to how critical data hazard mitigation is for keeping this complex pipeline fed.
- Dedicated Branch Pipe: There is a specific execution unit to handle branch instructions, which contains the sophisticated branch prediction logic needed to minimize control hazards.
4. Pipelines and Predictability: The Real-Time Challenge
Your work with ISO 26262 requires a focus on functional safety, where timing predictability is paramount. This is where pipelining becomes a double-edged sword. Features that boost average-case performance, like deep pipelines and dynamic branch prediction, make the worst-case execution time (WCET) incredibly difficult to analyze.
Execution Time Analysis for Embedded Real-Time Systems
The paper 'Execution Time Analysis for Embedded Real-Time Systems' provides an excellent perspective on this challenge.
Please read the following sections: '3 Hardware Timing', '3.2 Long Timing Effects', '3.4 Branch Prediction', and '3.5 Timing Anomalies'. You don't need to absorb all the details, but focus on understanding why these hardware features make execution time so variable and hard to predict.
Here are the critical takeaways for someone in your field:
- Increased Variability: Pipelining, caches, and branch prediction create a large gap between the best-case and worst-case execution times. A sequence of code might run very fast if everything hits the cache and branches are predicted correctly, but very slowly if not.
- Long Timing Effects (LTEs): The execution time of an instruction can be affected by other instructions that are far away from it in the program flow, not just its immediate neighbors. This makes simple, additive timing models inaccurate.
- Timing Anomalies: This is a counter-intuitive phenomenon where a local "improvement" (e.g., a faster memory access due to a cache hit) can cause a change in pipeline scheduling that results in a longer overall execution time for the program.
For hard real-time systems, you cannot rely on average performance. You must prove that tasks will meet their deadlines even in the absolute worst-case scenario. The complex, history-dependent behavior of a modern pipeline is a primary reason why WCET analysis is a highly specialized and challenging field.
Interview Corner
- "What is instruction pipelining, and what is its primary performance benefit?"
- Hint: It's an implementation technique where multiple instructions are overlapped in execution. The key benefit is increased instruction throughput (more instructions completed per second), not decreased instruction latency.
- "Can you describe the three main types of pipeline hazards?"
- Hint: Structural (resource conflict), Data (dependency on a result not yet available), and Control (branches/jumps). Be ready to give a short example for Data or Control hazards.
- "When a CPU encounters a branch instruction, what are the challenges for the pipeline, and how are they managed?"
- Hint: The challenge is a control hazard—not knowing which instruction to fetch next. It's managed with branch prediction. If the prediction is wrong, the pipeline must be flushed, which incurs a performance penalty.
- "You're working on a safety-critical system. How do features like deep pipelines and branch prediction complicate your work?"
- Hint: These features introduce significant variability and unpredictability in execution timing. This makes it extremely difficult to calculate a safe and tight Worst-Case Execution Time (WCET), which is essential for guaranteeing that real-time deadlines are met under all circumstances as required by standards like ISO 26262.
Conclusion
Today we've delved into the engine room of the processor. You now understand that modern CPUs don't execute instructions one by one, but rather use a sophisticated assembly line approach.
Key Takeaways:
- Pipelining increases instruction throughput by overlapping the execution stages of multiple instructions.
- Execution timing is impacted by pipeline hazards:
- Structural: Resource conflicts, often solved by hardware design.
- Data: Instruction dependencies, often solved by forwarding.
- Control: Branches and jumps, managed by branch prediction.
- A misprediction or unresolvable hazard leads to a pipeline stall/flush, which degrades performance.
- Real-world ARM pipelines (like the Cortex-M7's) are complex, superscalar designs optimized to minimize hazards.
- For real-time systems, the dynamic and history-dependent nature of a pipeline makes WCET analysis a major challenge.
Next Lesson Preview:
We've covered the processor's state and how it executes instructions. Next, we'll look at the rules of engagement for software. We will explore the ARM Procedure Call Standard (AAPCS), which defines how functions call each other, pass parameters, and return values. This is the convention that allows C code, assembly, and libraries to interoperate seamlessly.