Вы находитесь на странице: 1из 3

Wed, 23 Feb 2011, 02:46

A student writes:
> Professor Patt,
> You mentioned in the class that with Tomasulo algorithm it is not
> possible to maintain precise exceptions and hence we need an extra
> structure to commit or retire the instructions in program order.
> My doubt is regarding the condition codes which get changed during
> the execution of the instructions. If the instructions execute out
> of order and change the condition codes, but an exception occurs,
> how is the preciseness maintained?
>
> Also, generally, how are the condition codes maintained for out-of-order
> execution?
>
> Thanks in advance,
> <<name withheld to protect the student who is thinking deeply>>
These are good questions, and involve concepts that I plan to go into more
detail later in the semester. I must admit I added them to Monday's lecture
because they are important with respect to modern microprocessors, rather
than being central to the Tomasulo algorithm. And I will often err on the
side of giving you more rather than less with respect to fundamental things
you will see after you graduate.

So, given that...
An exception is an event that prevents an instruction from completing
successfully. In the context of Tomasulo, a MUL instruction that produces
a value too large to represent (OVERFLOW) or too small to represent other
than as 0 (UNDERFLOW) are examples of exceptions.
Let's say that instruction A caused an exception. A precise exception is
one in which the machine is able to be restored to the state it would have
been in if all instructions prior to instruction A properly completed
execution, but no instruction after that. For example, suppose we have
instructions 1,2,3,4,5,6,... and suppose instruction 4 caused an exception.
A machine is said to maintain precise exceptions if it can restore the state
that it would have been in if instructions 1,2,3 had executed completely and
no instructions after that had executed.
The IBM 360/91, using the Tomasulo algorithm, did not maintain precise
exceptions. We can see that from the example we did in class yesterday.
Let me reconstruct part of it here, with a small change to emphasize a point.
Instruction 1. MUL R3,R1,R2: F D v v v v v v R3
Instruction 2. ADD R5,R3,R4: F D v v v v R5
Instruction 3. ADD R4,R6,R7: F D v v v v R4
Suppose instruction 2 caused an exception, which we would know at the end
of cycle 13. Unfortunately, instruction 3 completes execution at the end of
cycle 9, and writes its result to R4, destroying whatever was there before.
The machine is not able to construct the state it would have been in if
instruction 1 had executed, but instructions 2,3 had not. Why? Because
before instruction 2 executes, R4 should have the value that was destroyed
by instruction 3. Therefore, no precise exeptions. Got it?
Note that this is particularly bad since instruction 3 has destroyed the
value in R4 which instruction 2 (the instruction that caused the exception)
used as a source operand. Which means the computer can not even examine
the two sources to help figure out what went wrong. [Yes, we could have
saved that value to handle this situation, but this is a small example.
In general, to do so would require a lot of very complicated "saving" values.]
Second issue: How to maintain precise exceptions. The simplest way is the
way my students and I came up with in 1985: the use of a value buffer. Most
of us now refer to the structure as the Reorder Buffer. It works very simply
by assigning the next sequential entry of the Reorder Buffer to the next
sequential instruction being fetched and decoded. That is, if the sequential
instructions are 1,2,3,4, then the assigned entries are locations 1,2,3,4.
When an instruction executes, it puts its result into the corresponding
location in the Reorder Buffer, but does not write the result to the register.
In the three-instruction example above, in cycle 9, instruction 3 finishes
execution and writes its result to location 3 of the Reorder Buffer and NOT to
R4. In cycle 14, when instruction 2 writes its result to location 2, it can
also write its result to R5. When instruction 2 writes its result to R5,
instruction 3 knows it can then write its result to R4. We call the act of
writing the result to the register "retiring" the instruction. In this way,
even though instructions can execute out-of-order, i.e., when their operands
are ready, they retire in the same order that they were fetched and decoded.
By doing this, it can never be the case that a later instruction can destroy
the state seen by an earlier instruction. Ergo, with a Reorder Buffer,
precise exceptions are maintained.
Last issue: condition codes in the context of out-of-order execution.
I suspect the confusion here is because you know condition code values can
change after every instruction's execution if the instruction stream consists
of loads and operates. But the contents of a register can also change every
instruction, as shown below:
LDW R1,R2,#10
LDW R1,R1,#5
ADD R1,R1,R5
Note that not only the condition codes but also the contents of R1 are changed
as a result of each of the above instructions. And, yet, you do not have a
problem with R1, correct?
So, one simple solution to out-of-order execution with condition codes is to
augment your register file with an entry for NZP. For example:
R Tag Value
-
R0: | | | |
-
R1: | | | |
-
R2: | | | |
-
R3: | | | |
-
... | | | |
-
| | | |
-
Rn: | | | |
-
NZP: | | | | | |
-
To complete the story, we note that branch instructions use the condition
codes as source data. Not a problem. When we decode a branch instruction,
we assign the current tag of NZP. When the instruction associated with that
tag completes, the branch instruction will get the NZP that was generated.
Condition codes with Precise Exceptions: Also not a problem. Let each entry
in the Reorder Buffer have two parts, the value produced and the condition
codes produced, if that instruction produced condition codes.
OK?
Good luck with the rest of the course.
Yale Patt

Вам также может понравиться