 In the previous section, we built a processor. We were able to get it to do a number of major instructions, really everything that we needed it to do, and it works. We could write pretty much any program that we'd like using this processor. But, as always, we'd like our processors to run fast. We'd like our processors to run faster than they already do. So in this section, we're going to be trying to improve the performance of this processor. We're going to be focusing on a specific tactic which is pipelining. And at the end of this section, we'll have built this processor. And you can see some of the familiar elements that we had before, the instruction memory, registers, ALU, data memory, and so on. But we've added a whole bunch of extra hardware and a lot of additional stuff to control how our hardware works. The basic idea behind pipelining is that we're going to break our processor up into a series of smaller chunks. Now, each instruction will only need to occupy one chunk of our processor at a time. So that will free up the rest of the processor to run other instructions. This means that we'll actually be able to have five instructions running concurrently in our five-stage pipeline, which will have a number of effects for us. One is that we'll get a higher clock rate. Our processor will appear to run much faster than it did before, even if it's really just doing the same amount of computation. But we will actually get some greater performance out of this because we'll have five instructions running concurrently. So we could potentially get five times the performance that we had before. We won't usually get that much speed up, but we'll be able to look and see what kind of speed up we get and in what conditions. However, this performance does come at a cost to us. The most obvious thing is that our processor is suddenly a whole lot more complicated. There are a lot more moving pieces here, and things are going to work a little differently than they did before. This also has the problem that it's going to produce some instruction-level conflicts. If we have one instruction that's producing some data and the next instruction wants to consume that, then we're going to have some issues there. We'll have issues with our branch statements when we don't know if we are going to take this branch until relatively late in our pipeline when we've already wanted to pull in a couple more instructions after it. So we're going to see what will happen in all of these cases and how we can ameliorate some of those effects.