Tue, 28 Apr 2009, 22:05
A student writes: Dr. Patt, In class you mentioned data dependencies and control dependencies. You said there are several kinds of data dependencies, and that a flow dependency is one of these. I don't think you explained what the other kinds are. But I might have missed that. No, I generally discuss them all in the context of data flow, and we have not gotten there yet. Since you asked, let me do it here. First control dependencies: Suppose you have the code: ... BRn A ADD R1,R2,R3 A LD R4,B ... The ADD instruction is control dependent on the BRn instruction. That is, whether or not the ADD executes is dependent on whether or not the conditional branch is taken. Note that the LD instruction is not dependent on BRn, since the LD instruction gets executed regardless. We say the LD is control-independent of the BRn instruction. Next data dependencies. There are three. Some people refer to them as hazards, a term I do not like, because if you design properly, there is never a problem. Since so many people use the term hazards in this ill-conceived way (in my view), I will give you both sets of terminology. a. Flow dependency (also called Read-after-Write (RAW) Hazard). Best shown by an example: X + YZ. That is, the sum of X and the result of multiplying Y and Z. One can not do the Add until AFTER one does the multiply. The result of the multiply is needed as a source of the add. The machine language code would cause the computer to write the result of the multiply into a register BEFORE that register was read to get a source for the add. So, the write has to be done before the read. Ergo RAW. It is a "flow dependency" in the sense that the result of the multiply flows into the source of the add. This is part of the code and must be obeyed. ...although it is certainly true that one could rewrite the code. b. Write dependency (also called Write-after-Write WAW Hazard). This is most notable in code involving I/O devices or I/O control blocks. Simple example: code that writes to R0 which is then written to the screen. Suppose the program wishes to write: "You have mail" by writing the successive characters to R0 and after each, calling the TRAP handler to write the next character to the screen. You would be unhappy with: "Yuo emahv ila." There is an output dependency between successive writes to R0. This is never a problem in out-of-order machines because one would assign different tags for different instances of R0. c. Finally, anti-dependency (also called WAR Hazard). This is the case where a dependency does not really exist, and is never a problem with o-o-o implementations because different tags are assigned to different instances of a register. Again, an example is illuminating. ... ADD R1,R3,R2 ADD R2,R4,R5 ... The anti-dependency says that you have to read R2 for the first add BEFORE you write R2 in the second add. You might say, obviously! If I wrote R2 before reading R2, I would be reading the wrong value for R2. As I said, tags guarantee that. But suppose I did not have tags, and somehow my implementation stalled the first add (maybe R3 was the result of a LD that took a cache miss) and I did not read R2 until after I read R3 (after the LD completed), and suppose for some reason I let the second add complete and write to R2 before the LD completed. Then I would be reading the value in R2 produced by the second add, when I should have been reading the value in R2 that was there before the second add completed. Ergo, antidependency. Easy to make sure this never happens by sourcing the registers in the front end in-order part of every pipeline. OK? Bottom line is that the tagging gets rid of the problem for antidependencies and write dependencies, and provides the mechanism to ensure that flow dependencies are dealt with properly. Hope this helps. Good luck on the exam tomorrow. Yale Patt "Data dependency (Flow dependency)" is listed as a buzzword. But these are not the same. As I said above, a flow dependency is a type of data dependency. Right? The buzzwords from Fall 2005 and Spring 2007 say that a data dependency is "one of the three data dependencies: flow, anti, write". However, write dependencies are not explained anywhere in the buzzwords. Can you please explain that? An in-order pipelined machine has to handle control dependencies and flow dependencies. Are write dependencies and anti dependencies a problem is such machines? Does an out-of-order machine have to handle all of the dependencies mentioned above? Thanks, <<name withheld to protect the student inundated with dependencies>>