Divide the pipeline into three parts:
Once all operands are ready and the functional unit is free, the operation is performed.
The commit unit determines when it is safe to write results to the register file or memory.
Two choices for commit:
In-order completion is where instructions are committed in program execution
order. If an exception occurs, only those instructions before the exception
will have written results.
Out-of-order completion does not have such precise interrupts. There
may be a need to undo some instructions.
To make things even more complicated, consider dynamic branch prediction. This leads to speculative execution, since you do not want to keep your functional units idle while you wait for a branch condition to be determined. Again you will need to undo instructions.