CS 473

Homework 4: Pipelining your CPU

Due Monday, November 8, 2004

Paper

Consider the following sequence of MIPS code:

addi  $1, $0, 100
add   $2, $0, $1
lw    $3, 100($2)
lw    $5, 200($3)
sw    $5, 100($3)

Draw a Gantt (timing) chart showing how these four instructions are executed. Where a stall is necessary, show it by "stretching" the instruction decode stage. Where forwarding is necessary, show it by drawing an arrow from the stage where the data is produced to the stage where it is consumed.

Programming

For this assignment, you need to pipeline your machine. You won't need to worry about hazards (no forwarding, no stalls). I want you to implement Figure 6.27, augmented as needed (you already figured out what augmentations were needed when you did HW3).

As I said before, you can use either your solution as your starting point on this assignment, or mine. In any event, this one should take less work than HW3 did.

How To Pipeline It

First, you need to add pipeline registers. It's probably most convenient to do this as a separate function for each stage of the pipeline, with by-value parameters for each wire coming in from the left and by-references parameters for each wire going out to the right. When the function is called, it "latches" its inputs and transfers them to its outputs.

As an example, the IF/ID pipeline register would look something like this:

void ifid(Address pcIn, Instruction instrIn, Address *pcOut, Instruction *instrOut)
{
    *pcOut = pcIn;
    *instrOut = instrin;
}

Now, you just define a variable for every wire coming into the pipeline registers, and a variable for every wire going out. In effect, you're cutting just about every wire from the last HW, and putting a pipeline register into the gap.

Finally, you leave your existing calls to functional units as they are, but then follow up with a call to each pipeline register.

Output

Ummmm.... on HW3, people were much more creative about their outputs than I ever would have dreamed possible... so I'm providing an output function, which you can get here.

void report(uint32_t pc, uint32_t registers[32], uint32_t datamemory[1024]);

What this function does is report any changes made to the visible state of the computer on every execution cycle.

The function takes three parameters:

pc
This is the program counter, containing the address of the instruction you are about to fetch and execute.

registers
This is your register file.

datamemory
Your data memory.

This should be called at the beginning of every execution cycle, so now your main program will look something like this:

/* read the program to be executed */

while (1) {
    report(pc, data_memory, registers);

   /* do all your functional units, except the pipeline registers */

   /* do the pipeline registers */
}

I've modified my solution to HW3 to use this report function.


Last modified: Thu Nov 4 16:07:28 MST 2004