Pipelining
The basic idea behind pipelining is that we can have a different
instruction use a different part of the data path at every point in
time. The figure above shows how three instructions could be
overlapped in a pipelined implementation. A pipelined datapath would
require that each stage remember the instruction it is supposed to be
executing since the previous stage can not provide that information;
it is busy working on the subsequent instruction. The pipelined
datapath is essentialy the same to the single-cycle CPU datapath but
had buffers between every stage that record the information necessary
to drive the subsequent stage of the pipeline. The contents of these
buffers get forwarded across the pipeline stages with each clock tick.
Data Hazards
In an ideal world using a pipeline should allow a program to run as
many times faster as is the depth of the pipeline. However it is
possible for an instruction to try and use a register that is being
modified by a previous instruction. If the previous instruction has
not yet completed then the current instruction may read stale register
values. The easiest solution to data hazards is to stall instructions
that have dependencies on previous instruction until these
dependencies have been resolved (i.e. the previous instruction have
completed execution). Alternatively one can try and bypass some of
the pipeline stages and feed results from executing instruction
directly into the ALU where dependent instructions can use them. This
is called data forwarding.
Control Hazards
Another problem with pipelines happens with branch instructions.
Since when we decode the instruction we do not know whether the branch
will be taken or not we do not know where to fetch the next
instruction from. One solution is to stop fetching instruction until
the branch has been resolved and we know the new PC address. An
alternative is to guess which way the branch will go and start
fetching from that address. If the guess is wrong we then need to
kill these instruction and start fetching from the correct address.
Exceptions and Pipelines
Exceptions are detected the same way they were detected for the
single-cycle CPU implementation. However when an exception is
detected we need to make sure that no instruction that follows the
offending instruction is executed. This is accomplished using the
same mechanism used for dealing with Control Hazards; killing the
instructions in the pipeline that follow the offending instruction and
starting to fetch from the address where the exception handler
resides.