 Today's lecture on Instruction Pipeline and particularly we shall focus on pipeline hazards in this lecture and briefly we can recapitulate what we discussed in the last lecture. You may recall that I mentioned about the mentioned that as computers execute billions of instructions per second pipeline, pipelining instruction execution is the most common approach to improve CPUs performance. So, since that is the primary job of a processor fetch and execute instructions instruction pipelining is profitable and widely used since 1980s. And I mentioned that main idea behind pipelining instruction pipelining is to divide instruction execution across several stages. That means, we divide it into sub tasks and then across different stages it is divided and each stage accesses only a subset of the CPUs resources that I have elaborated in details. And particularly we have considered a classic five stage risk pipeline as an example where the pipeline is divided into five stages instruction phase instruction decode execute memory read or write and then write back. And different instructions are in different stages of execution simultaneously and how it happens and how with the help of pipeline resistors this is maintained I have discussed in detail. And we have also seen that if the ideal conditions are satisfied then it is possible to input one instruction at a time or produce result for one instruction at a time. So, it gives you a CPU of CPI is equal to one cycles per instruction that is equal to one in the ideal situation. Question actually arises whether this is true for all possible situations and I mentioned about a parameter speed up. And we have seen only when we are executing large number of operations then only you get the you reach the ideal speed up. And as you can see if you have got case stages then if the number of operations is very few then you can see the speed up factor is initially one if the number of operation is only one. If the number of operation increases in our case number of instructions increases to be executed then you can see the speed up increases gradually. And it attains a value of k that is the number of stages only when you have got very large number of instructions getting executed. So, is true for any value of k for k is equal to 10 the same is the situation. And we have also discussed about the limits on pipeline stages the number of stages if you increase it helps you in improving the performance because speed up increases. But as you increase the number of stages we have seen we have to add pipeline resistor as you add a new stage. So, that is an overhead as you keep on adding number of stages you have to keep on adding the pipeline resistors as well. And as you keep on adding the pipeline resistors with the number of stages the overhead keeps up increasing. And as a consequence you can see the cost performance the performance cost ratio does not really increase linearly as the value of k increases. So, it increases and then attains a peak value and if you further increase the number of stages then the performance degrades. And that actually puts a limit on the number of stages that a pipeline processor should have. And this particular optimal value are being tried in modern processors and the number of stages is increased as many as possible. But obviously, there is a upper limit beyond which it does not give you good result. So, the resources keeps on increasing as the number of k increases resource requirement keeps on increasing. Now, today we shall focus on pipeline hazards question arises should we expect a CPI of 1 in practice. If CPI is 1 then it is the ideal ideal situation ideal conditions are met. What are what were the ideal conditions number 1 ideal condition was that the instructions are independent. They can be executed independent of each other and only then you can achieve a CPI is equal to 1. But unfortunately we cannot have complete independent the instructions cannot be fully independent. And so, we cannot really get a CPI of 1 and there is some limit and that limit is imposed by hazards. So, we shall discuss about hazards and what is a hazard. Hazards are circumstances that prevent the next instruction in the instruction stream from executing during the designated clock cycle. We have seen we are fetching in our program order we have a sequence of instruction 1 followed by instruction 2 followed by instruction 3 followed by instruction 4 and so on. So, now we would like to execute these instructions one after the other and whenever you do pipelining we are we are obviously doing kind of some kind of I mean overlap execution. Now, whenever you are trying to do it in this way you will find that where I 3 should have been executed we are not able to do because of hazard or where I 4 is supposed to be executed cannot be executed because of dependence among the instructions and that is known as hazard. And the hazards can be broadly divided into three major types what are the three major types number one is structural hazards and structural hazards arises when you do not have enough resources to keep all the instructions moving. Initially in our ideal situation we assume that there is no resource constant, but this cannot be really true in practice because always there will be some resource constant because you would like to optimize the performance for a given cost. So, the cost will keep on increasing as you put additional resources in the system. So, there will be the structural hazard will arise will not arise if you have unlimited resources, but whenever you impose some restriction on the resources then structural hazard arises. How let me I shall explain with the help of an example, but before that let me explain the other two types of hazards second type of hazard is known as data hazards. So, that data hazards arises because data results of earlier instructions not yet not available yet that means what can happen suppose these are the instructions which you are executing one after the other that instruction 2 may require some data which is produced by instruction I 1. And whenever I 2 is trying to read that data then I 1 has not yet written it into the register. So, we have seen that primary means by which the data flow is taking place is through registers because all the ALU operations are involving registers. So, in case of our risk processor. So, if the result is not yet written into the register then if the same data is needed by a subsequent instruction then this data hazard will occur. Third type of hazard is known as control hazards control decisions resulting from earlier instructions not yet made. So, do not know which new instruction to execute. So, whenever you will find that there is a if then else type of statements present in your program. Now, that condition for which I mean condition on which that branching depends if something is true then it will execute a code sequence if that is the condition is not true then it will execute another code sequence. But if the condition is not yet known then which code sequence to be executed because if the code sequence to be executed is known then the processor can fetch from the memory that particular code sequence. But if that is known then processor needs to wait till the decision is known and that leads to what is known as control hazard. So, I shall elaborate these hazards one after the other first let us focus on structural hazard. The structural hazards occur when two or more instructions need the same resource. We have seen that an instruction is divided into say classically five stages say I 1 we have got instruction fetch instruction decode then instruction execution then memory operation then write back. So, this is for instruction 2 we are executing in overlap manner. So, this is cycle 1 this is cycle 2 cycle 3 4 5 then instruction fetch decode instruction execution memory operation and write back. So, this is how it happens instruction fetch instruction decode instruction execution memory operation and so on. So, this is how the instructions are executed in this way and in this direction you have got the clock cycle or time. Now, we find that whenever we go to this particular point say you have got instruction 4 where instruction fetch instruction decode is going on. Now, if you look at this point here we are performing some memory operation and also we are performing instruction fetch. Now, if you have got one common memory if you have got one common memory then what will happen these two operations cannot be performed simultaneously this particular instruction 1 will be writing some data into a I mean it will involve memory that means it will access memory may be load or store whatever it may be and here the instruction 4 is being fetched that is also stored in memory. That means for instruction and data we have common memory then there will be a hazard here because you may recall that in our earlier processors like in Princeton architecture proposed by von Neumann there we had got only one memory common memory. So, if you have got only one memory then there will be a structural hazard at this point. Similarly, for example, here you are doing instruction execution and instruction fetch instruction decode instruction execution and instruction execution may involve some computation it will always involve some kind of computation. Now, whenever you are performing instruction fetch and instruction execution you are doing instruction execution and instruction fetch and instruction decode. In such cases also you will see you will require some adders to generate the next address whenever you are doing instruction fetch you are calculating the next address and whenever you are performing instruction execution you are using the adder. So, in these two cases if you use the same ALU to perform both the thing that means calculation of the next address as well as I mean computation of the operation addition subtraction whatever it may be then again there will be a hazard. And that is the reason why you may have noticed in our simple pipeline we had got separate adder and also in addition to that the arithmetic and logic unit ALU. So, it is not done by the same ALU. So, what we are doing we are adding additional resources so that this happens. So, in this particular diagram we have seen that if we have a shared memory then you have to know other alternative, but to stall the execution. In other words what you will do that instruction fetch of the fourth instruction is delayed till the fifth cycle and you are losing one instruction cycle. So, one cycle is lost whenever you have got a single memory and that is the reason why that Harvard architecture is used where we have got two separate memories one for data and another for instruction. So, whenever you have got two separate memory is no problem this particular operation will involve the data memory access of data memory and this particular in this here if you fetch the instruction then it will involve program memory. So, the hazard is overcome. So, this is how with the help of additional resources you can overcome the structured hazard. So, a pipeline is installed for a structural hazard when both instructions and data share the same memory shown is in this particular example. Now, question is what are the different ways by which structural hazards can be overcome number one is duplicate resources as we have already seen we are we are duplicating the resources adding more memories adding adders such that the structure hazard is overcome. Another alternative way of overcoming structure hazard is to pipeline the resource. So, a particular resource may be pipeline. So, if you can pipeline a particular resource can be it can be an ALU it can be some other resource memory. If you can pipeline its operation then what you can do since in a pipeline system we have seen different operations can be performed for different tasks in a overlap manner. So, they are also then also it is possible to overcome structure hazard, but all resources cannot be pipeline unfortunately. So, if a particular resource can be pipeline then instead of duplicating it will go for pipelining the resource that will be more cost effective in the sense pipelining involves much lesser cost than duplicating a resource. So, this is a better alternative, but that alternative may not be always possible and not that is why duplicating resources is commonly used because it is simple easy to implement and always possible. Then reorder the instructions. So, this is the third alternative where whenever you are facing some hazard for example, if there is any way by which two instructions are causing some kind of hazard. So, what you can do the instruction sequence can be changed that you can reorder the sequence of instructions. So, without affecting the result that means the program without affecting the program flow means the that is that was intended in your source program whatever outcome was expected that that output should be obtained without violating that if you can reorder the instructions and overcome the hazard that is also possible. So, you can reorder instructions and it may be too expensive to eliminate a structural hazard in which case pipelining should stall. So, the last resort is to stall the pipeline. So, whenever none of them is physical duplicating resource is very expensive pipelining is not feasible reordering of instructions is not feasible in such case you have no other alternative, but to stall the instruction for a cycle and that will definitely overcome the structural hazard. So, whenever you are doing this no new instruction is issued until the hazard has been resolved. So, in the previous case we have seen just by introducing one bubble one I mean one stall we are able to overcome the structural hazard for our five stage pipeline. So, we have discussed about the structural hazard. Now, let us focus on data hazard. So, what is the primary reason for data hazard that we shall explore our as I mentioned our earlier assumption that instructions are independent is not true there will be dependences. So, dependences are the root cause of data hazard. So, we shall do the analysis of different types of dependences to understand why data hazard occurs and how it occurs. So, first of all you should understand these two aspects number one is dependences are property of program that means that property of program is independent of the machine implementation. A program has been written a source code is there and that source code has incorporated some dependences among different instructions. So, this is independent of the processor. So, that part is the property of programs that cannot be changed by whenever you go for implementation. Secondly, whether a dependence leads to an actual hazards and whether the hazard actually causes a stall or properties of the pipeline organization. That means these two aspects are different one is the property of the programs another is the outcome of the pipeline organization. That means whether a particular dependence will lead to some hazard and stall that will depend how the pipelining is done. And there are three main types of dependences in a program we shall explore three main types of dependences. Number one is known as data dependences, second is known as name dependences, third is known as control dependences. So, let us try to understand these three different types of dependences that is inherently present in a program. So, first we shall focus on data dependences. So, an instruction j is data dependent on instruction i if either of the following conditions hold. Number one is there is direct data dependence instruction i produces a result that is used by instruction j as it is shown in this particular code r 1 of operation r 2 you are performing some arithmetic operation or logical operation on the content of r 1 with that of the content of r 2 and you are storing the result in the register r 3. Now, that register r 3 is being used as the source of operation in case in the second instruction where you are performing the content of r 3 operation content of r 4 and the result is being stored in r 5. So, in this case you can see there is a direct data dependence that instruction 2 is data dependent on the instruction 1. So, or you can say this is the j and this is i instruction j is data dependent on instruction i. So, this is the direct data dependence and it may not be always direct data depends and may not be always present there can be data dependence can be transitive in nature. So, in such a case instruction j is data dependent on instruction k and instruction is data dependent on instruction i as it illustrated with the help of this example. Here, as you can see that instruction 2 second instruction is data dependent on the first instruction, but the third instruction is not data dependent on first instruction directly, but you can see the second instruction is data dependent on the first instruction, and third instruction is data dependent on the second instruction. So, there is a kind of transitive relationship on data dependency, and here we can say that this r phi that third instruction is also data dependent on first instruction may not be directly, but there is a transitive data dependence. However, dependence within a single instruction such as at D at double r 1 comma r 1 comma r 2 is not considered as dependence. So, this cannot be considered as dependence, because in this case all the three operands are involving same registers, and this is not treated as a dependence. Now, let us come to another example, if two instructions are data dependent, they cannot be executed simultaneously or be completely overlapped. Why it is necessary to analyze data dependence is very clear, because whenever we try to implement pipelining and try to execute in a overlap manner that will lead to hazard, and we have to stall. That is the reason why if two instructions are data dependent they cannot be executed simultaneously or be completely overlapped either they cannot be completely overlapped or simultaneously they cannot be executed. So, let us look at this program loop LD f 0 comma 0 r 1 here as you can see the f 0 is the source of operand in the next instruction. So, there is direct data dependence between these two, and also there is direct data dependence between first and third. So, floating point operations are being performed by this operation, and first in the first instruction you are loading a particular operand a scalar value into a register f 0, then you are performing addition with the content of a register f 2, and storing the result in f 4. And again here also we are using the you are storing the value another I mean then the data that is f 4 is being loaded in the stored in the memory that is the instruction that is being performed. And here also you can see that r 1 comma r 2 r 1 comma r 8 and here branch not equal here also there is data dependence, because you are performing some kind of subtraction you are so that the it is acting as a pointer. So, it points to the next element, and that is the reason why it is being done, and in the next instruction branch operation is dependent on that. So, there is a dependency here, so in this particular loop you find that there are several data dependence is present even within this state line code that is present in this program. So, a data dependence conveys three things why it is necessary to analyze data dependence, because a data dependence will lead to three things or it conveys three things that first of all is the there is a possibility of hazards. So, if there is data dependence there is a possibility of hazard second is the order in which the results must be calculated. That means, the order in which the instructions are appearing which is known as program order that program order needs to be maintained. Data dependence also ensures that the maintenance of this program order, and this data dependence also gives an idea of the upper bound on how much parallelism can be exploited. So, later on we will see we shall not only restrict to pipelining, we shall go for other type of processing like superscalar architecture, VLIW architecture where there will be multiple processing elements. So, where we shall be trying to exploit instruction level parallelism in a little different way, so there also you will find that you will be executing some operations in parallel. Now, what kind of instruction level parallelism in addition to pipelining whenever we shall go for other types of instruction level parallelism, what is the degree of parallelism that is present in the program inherent in the program that will decide the order of this upper bound on how much parallelism that is present. So, this data dependence analysis is very important because of these three issues. So, as I mentioned data dependence can limit the instruction level parallelism, a dependence can be overcome in two different ways. Now, suppose you have identified that there is a data dependence. So, in such a case what are you going to do? There are two possible alternatives number one is you will maintaining the dependence by avoiding a hazard. So, you will maintain the dependence and you will also try to avoid the hazard somehow how that we shall discuss in detail little later. So, this is one possibility that without changing the data dependence you will somehow avoid data hazards or avoid stalls that is one possibility. Second alternative is that you will modify the code itself that means, you will eliminate a dependence by transforming the code. You will modify the program such that the data dependence which was existing is eliminated. So, thereby avoiding hazards and stalls which is outcome of the data dependence. Now, question is how do you really detect data dependence? So, data dependence may flow between instructions in two ways. Number one is through registers, number one and number two is through memory locations. So, by looking at the program you can by observing the program you can detect data dependence if same register is involved or if some memory address is involved. So, whenever same registers involved through which data flow is taking place then it is very easy to detect data dependence. That means when data flow is through register detection is rather straight forward. On the other hand when data flow is through memory location detection is very difficult. Detection cannot be done very easily whenever it is through registers. Let us consider two different examples why it is difficult. Two addresses may refer to the same memory location, but look different. For example, we have used two in two separate instructions. In one instruction we have used this R 4. This is the address that is generated. That means in this case the effective address is equal to content of R 4 plus 100 that is the effective address. So, this is how the effective address is calculated. Another instruction is there where the instruction is this operand address is specified by this. So, in this case the effective address is equal to content of R 6 plus 20. Now, it may so happen that this effective address 1 and effective address 2 may be same. So, if you analyze the program then you can see although the addresses generated are same, but by observing the program it is not possible to say that the effective address will be same. The reason for that is the value which will be present in R 4 and value that is present in R 6 can be dynamically modified while executing a program because memory locations the effective address that will be generated by calculating the with the content of a register and some displacement that is provided as part of the instruction that will be that cannot be observed that cannot be detected by simply by observing the program. Similarly, there is another example the effective address may differ from one instruction to the other. So, in the second case for example, the in two different instances in the instruction sequence you have the same register in and same displacement. Now, what can happen in between the register value may have been changed. So, although it may appear that these two will produce the same effective address, but in reality they may not generate the same effective address. The reason for that is that value of R 4 may be dynamically changed while executing instructions. So, in this case we find that whenever the data dependence is through I mean when the data flow takes place through memory then it is difficult. So, later on we shall discuss about how this detection can be done whenever it involves memory, but whenever it is involving registers it is rather easy to detect. Now, the third type of second type of dependence is known as name dependences. So, name dependences are two instructions use the same register or memory location called a name. So, there is no true flow of data between the two instructions we have taken up example let us consider one example is say a is equal to b plus c and another is a is equal to b plus q. Now, here what you are doing you are adding the I mean value taken from may be memory location where b is stored and another memory location where c is stored and then you are storing in a memory a. Similarly, here you have got another one another instruction where you are storing in same memory, but the operands p and q are different. Now, in this particular case the there is no data dependence in the sense there is no flow of data from one instruction to another, but this will also lead to a kind of dependence and there are two types of dependences one is known as anti dependence another is known as output dependence. So, let me see let us see what are these two dependences what is anti dependence and what is output dependence. So, anti dependence occurs between two instructions i and j if j writes to a register or memory location that i reads original ordering must be preserved to ensure that i reads the correct value. So, here as you can see in the first case you are reading an operand for the first form register 8 and then performing this operation add the content of f 6 you are adding with the content of f 8 then storing the result in f 0. Now, you have got another instruction which is following the first instruction where you are storing the result in f 8 I mean f 8 is equal to content of f 4 plus content of f 5. So, in the first case what is happening f 0 is where you are storing x 6 plus f 8 and the second one this is your addition and in the second case you are performing f 8 is equal to f 4 minus f 5. So, this is what you are doing now this is the program order now it may so happen that this particular instruction will executed before this instruction. So, if this happens then what will happen then whatever value was intended to be read by the first instruction you will get a different value because it has been changed by a subsequent instruction. So, a subsequent instruction has modified it and then you are reading it. So, we will not get the correct result. So, this is called the anti-dependence. So, this anti-dependence is arising whenever that program order is not being followed strictly and that will happen particularly later on we shall see in superscalar architecture this can happen. So, this is known as anti-dependence. Now, let us consider the output dependencies. So, output dependence occurs between two instruction i and j if and only if the two instructions write to the same register or memory location. Now, the ordering of the instructions must be preserved to ensure such that you know whenever in the same register or memory location two instructions are reading writing. Now, if the order is changed the finally what value will flow will be different that is why instead of I mean finally, written value corresponds to j instead of i. So, that can happen the program flow will decide one particular order and outcome of result is dependent on that, but the execution order may be little different and in such a case the result will not be correct and that is known as output dependencies and name dependencies are not true dependencies. Why we are calling name dependencies? Because registers and memory locations are essentially considered as names in which you are storing the operands. How can you overcome this? This output dependencies are not really true data dependencies and they can be very easily overcome by a technique known as register renaming. So, later on I shall discuss about it in more details. You can modify the name of the registers you can rename the registers and this problem will be overcome. So, this output dependencies can be overcome and then you can change the order of the execution finally, the third type of dependencies is known as control dependencies. So, it determines the ordering of ordering the of one of an instruction with respect of the branch instruction. For example, here if p is true p 1 is true then s 1 and you have got another if then else statement if p 2 is true then s 2. Now, whenever we have got this type of if then else type of statements present in your program we call s 1 is control dependent on p 1 because if p 1 is true only then you are doing this then s 1 else something else something else you will do and similarly s 2 is control dependent on p 2. Now, whenever this kind of control dependencies are present an instruction that is control dependent on a branch cannot be moved before the branch. That means an instruction that is present in s 1 cannot be moved before p 1 because then you may not get correct result if you move some instruction from that then part of the program before that if part this instruction if p 1. So, this should not be done similarly an instruction that is not control dependent on a branch cannot be moved after the branch. That means some instruction which is present before if p i should not be moved to this part that means then part. So, that also should not be done because in such a case that particular instruction will become control dependent on p 1 which was not true earlier. That means so whenever you do some kind of reordering of instructions you have to consider these dependencies and you should not modify the program in such a way. So, when program order is strictly preserved it ensures that control dependencies are also preserved. So, essential requirement is to maintain the program order and if it is strictly preserved then control dependencies are also preserved. For example, a simple example has been taken here say the first two instructions are data dependent. So, they cannot be reordered but you can see. So, here it is producing some value which is stored in R 2 that is being used in the second instruction branch instruction. So, you have got data dependence. So, this data dependency can be very easily detected and obviously, while executing your program that program order will be maintained. But you can see the second and third instruction v q z R 2 comma l 1 and here you have got load R 1 comma 0 R 2 here you can see there is no as such data dependence. There is no flow of data between these two instructions. However, you cannot really reorder these two instructions because if you do the reordering of these instructions then this may lead to incorrect results because in a whenever you are executing this program in a dynamic situation the input to an instruction may come from multiple sources. There is a possibility of coming the input from multiple sources and that is dynamically dependent on the execution when you execute a program. So, this particular although there is no data dependence but if you try to reorder these two instructions it may lead to problem. Now, I have already discussed about the data hazards in detail. It arises out of change of relative timing of the instructions by overlapping their execution. So, here we have got a simple program and there is lot of data dependence as you can see that R 1 the result is being stored in R 1 in the first instruction which is used as a source of one of the operands in the second instruction that is also used as source of operands in the third instruction. Now, a chain of instructions several instructions one after the other is data dependent on the first instruction. Now, how long this data dependence you will persist whenever you go for pipeline execution actually it depends on the pipeline depth and data dependence does not always mean that it will lead to hazard. So, let us see this particular diagram this will help you to understand how and when it happens. So, you can see here the four instructions following this first instruction add R 1 comma R 2 comma R 3 you have got three four instructions sub R 4 comma R 1 comma R 3 and R 6 comma R 1 comma R 7 or R O comma R 1 comma R 9 then XOR R 10 comma R 1 comma R 11. So, you find all the subsequent four instruction is data dependent on the first instruction, but will all of them lead to data hazard installs. So, you can see here writing of the result is taking place in the fifth cycle in the if you look at the execution of the first instruction, instruction fetch instruction decode execution then that memory operation which is not present in this instruction, but that cycle will be necessary. So, in the fifth cycle you are writing the result into the register. So, we find that before the fifth cycle was reached in the third cycle itself second instruction has already read the data. So, there is a red line and which implies that here there is a hazard data hazard. Similarly, in this case also the before the writing of the value in the register took place the reading of the upper end took place in the third instruction. So, as a consequence you can see there will be hazard for the second instruction as well, but so far as the third and fourth instructions are concerned they will not be it will not lead to any hazard because what has been done a technique known as split cycle has been used where writing is done in the first phase of the clock. So, you have a clock has got two phases. So, you are performing writing in this in this phase and reading you are performing in the second phase. So, this is a particular clock cycle. So, whenever you do this split phase then only that third instruction will not suffer from hazard. If split cycle is not done then the third instruction also will suffer a data hazard. So, in this particular case it is not read because you have been you are able to read the register value after it has been written. So, we find that although there are four instructions consecutive instructions are data dependent on the first instruction, but only the first two is leading to data hazard the next two there is no data hazard. So, you can classify the data hazards with the help of three different ways. So, classification of data hazards first one let us assume that we have got an instruction i be an earlier instruction j is a later one then read after write hazard is defined as j tries to read a value before i writes into it which is known as read after write hazard as it is shown here. This is the read after write hazard i you are writing some value in a register in the second instruction is reading the value read after write then second one is write after write i and j write to the same place, but in the wrong order. So, you can see they are writing in the same place, but you know if their order is different then it will lead to hazard known as write after write hazard. So, only occurs in more than one pipeline stage can write. So, in our case that simple five stage pipeline that we have already discussed where the second type of data hazard that is write after write type of data hazard will not be present. You can think over it and you will see this will not be present then third type of hazard data hazard that is known as write after read. So, in this case j writes a new value to a location before i has read the old value. So, j writes to a new value before i has read it. So, in this also will not occur in our five stage pipeline. So, this occurs only when if writes can happen before the reads in our case we have seen that write operation take place at the last cycle. So, before that read will always take place. So, this type of hazard will not be present in the five stage pipeline that we have already discussed. So, we can conclude our lecture with these statements do all kinds of data hazard translation to pipeline stalls. We have seen the answer is no whether or not data hazard results in a stall depends on the pipeline structure. And for the simple five stage risk pipeline that we have discussed only read after write hazard result in a pipeline stall. And instruction reading a register needs to wait until it is written. So, WAR and WAW hazards cannot occur because all instruction take five stages. Reads happen in the second stage we have seen write happens in the fifth stage no way for a write from a subsequent instruction to interfere with the read of a prior instruction. So, we can conclude that for our simple five stage pipeline only the first type of hazards read after write type of hazards can occur. The other two types of hazards like write after read and write after write type of hazards cannot occur. But there can be more complex pipeline the pipeline depth may be much longer later on we shall discuss some examples. And there this type of hazards may also be present all I am trying to tell for our simple pipeline it does not the second two types of hazards may not lead to I mean second two types of data dependences may not lead to hazard does not mean they will not lead to hazard at any point of time. They can lead to hazard whenever your pipeline depth is longer or you have got different types of pipeline structure. So, with this let us stop here. Thank you.