Program 3 -- CS 473.
This program is to help you understand pipelining and the need
to delay certain instructions due to a previous instruction's
values.
Pipelining is used to improve the time it takes to execute instructions.
If you recall, the basic process of an instruction execution is to
do the following:
LOOP
Use the PC to select an instruction from Memory
Place the instruction into a register I.
Execute "I"
(check for interrupts)
Increment the PC
Repeat LOOP
In about 50% of the time (or more), it is possible to separate the
Fetch from the decode from the execute. This means that we can do the following
T0 Fetch I1
T1 Decode I1 Fetch I2
T2 Execute I1 Decode I2 Fetch I3
T4 Execute I2 Decode I3 Fetch I4
.....
This only works IFF I2 does not depend on the values of I1. If
I2 depends on the values of I1, we have to "stall" I2 to allow I1
to execute.
This programming assignment is to take a list of instructions from the SCOOPY's
famous process (see data sheet below) and indicate which instructions
should be stalled.
We will define a stall IFF the registers in Instruction_K have their
values set in Instruction_(K-1). In this case, you are to INSERT
a new instruction called STALL between instructions K-1 and K.
In other words, if a register is used in I_K and it is set in I_K-1,
you must STALL (please keep in mind that several of the instructions
set a value to R0 or R1 even though they are not explicited listed
in the Assembly Line).
There are a number of instructions that need not be stalled.
For example
LI does not depend on any values from the previous instruction
IK does not depend on any previous values
Others
LD MAY depend on previous values if Rk is changes in the previous
instruction
JMP implicitly depends on R1
JMPNE depends on both R1 and R0 -- so if either is affected, you have to stall
You *MUST* write your program in C. You must document your code with the following
standards:
1) you must have your name, date, program title, program purpose, assumptions
on data input, etc as part of the header of the program (10 pt)
2) for every subroutine/function, you must have at least a description on
what that function is suppose to do and how it is used (5pt per instance)
3) for every "while", "for", or complicated "if" statement, I expect to see
at least one line explaining what that structure is doing. Statements
like "this is a while loop" are not considered documentation. A statement
like "cruise through the memory loading up values from STDIN" are good.
(5 pt per instance)
I believe programs should have decent, "high level", documentation in them. If
you choose to not document, your performance will suffer.
The input to your program will be a lines of Assembly language instructions.
Your output will be the same set with STALL inserted between the instructions
that need to be stalled.
SCOOPY's INFAMOUS PROCESSOR DATASHEET
16 bit word, 4 registers (R0- R3)
The instruction format (in general) is as follows:
bits
| 15 - 12 | 11 - 9 | 8 - 6 | 5 - 0
OP CODE Ri Rj Data
bits (LI only)
| 15 - 12 | 11 - 0
OP CODE Data
--control--
0000 LI -- Load R0 with the value from the last 12 bits of the instruction word
0001 LD Ri Rk -- Load Ri with the contents of Rk
0010 LM Ri -- Load R0 with the memory value refenced by Ri
0011 STO Ri -- Store R0 into the memory refence of Ri
0100 JMP -- Jump to the value stored in R1
0101 JMPNE -- Jump to the address in R1 if R0 is equal to zero
-- I/O --
0110 IK Ri -- input from keyboard a decimal number and place it into
Register i
0111 OM Ri -- output to the standard output the contents of Register i
in decimal format
-- datapath --
1000 CMP Compare R0 to R1. R0=1 if the same, R0=0 if not the same
1001 ADD Ri Add Ri to R0. The result goes into R0. Ie, R0=R0+Ri
1010 SUB Ri Subtract Ri from R0. The Result goes into R0. R0=R0-Ri
1011 INC Ri Ri=Ri + 1
1100 MULT Ri R0=R0*Ri
1101 DIV Ri R0=R0 div Ri
1110 MOD Ri R0=R0 mod Ri
-- extra --
Here is an example input and output.
Input
LI 20
LD R1 R0
LD R2 R0
LD R3 R0
INC R1
INC R2
INC R3
OM R0
OM R1
OM R2
OM R3
PC
HALT
Should Turn into
LI R0 20
STALL
LD R1 R0
LD R2 R0
LD R3 R0
INC R1
INC R2
INC R3
OM R0
OM R1
OM R2
OM R3
PC
HALT
Another example is
LI 20
LD R1 R0
LD R2 R1
LD R3 R1
HALT
Would be
LI 20
STALL
LD R1 R0
STALL
LD R2 R1
LD R3 R1
HALT
Example 3:
LI 20
LD R1 R0
JMP
Turns into
LI 20
STALL
LD R1 R0
STALL
JMP /node JMP depends on R1, which is set in the previous I/
Example 4:
LI 20
LD R1 R0
LD R2 R0
JMP
Turns into
LI 20
STALL
LD R1 R0
LD R2 R1
JMP /note the JMP depends on R1, but it is not SET in the previous I/