Okay. So, we've talked about structural hazard, or we've talked about pipe-lining basics. And now, we're going to go into the three main types of hazards. Structural hazard, data hazards, and control hazards. Let's start off by talking about structural hazards. Okay. So, let's, we'll review structural hazards here. So, structural hazards, as I said before, occurs when two instructions need to use the same hardware resource at the same time. And there's a couple approaches on how to resolve this problem. I mean, we can't actually throw up our hands and just stop the pipeline or maybe, maybe that kind of is one of the solutions. But, you need to somehow, think really hard about how to deal with the structural hazard. One thing you can do is you can explicitly avoid having different instructions that will be in the pipeline at the same time, use one structure at the same time. And, you can do this by the programmer, or maybe the compiler can do this. Next way that you can go about doing this is you actually have the hardware take care of, basically, all of the problems. And, there's some complexities to actually building this, but you want to stall the processor, or stall a portion of the processor, or stall the dependent instructions or just going to, you, you stall, let's say, the earlier one, when you go for the contended resource. So, a good example of this is if you have one resource, two things are trying to use it. You have a priority encoder in there and the priority encoder says, the earlier instruction gets to use that because if you sort of invert the priority order, you might end up with deadlocks. Another good way to do this is you actually can duplicate the hardware resources, or you can add more ports to a memory structure, which is sort of the colon of duplicating the hardware resource. And this is to some extent a solution that is used pretty widely in something like the, the MIPS pipeline, the basic 5-stage MIPS pipeline. It lets you duplicate certain resources. For instance, there's two memory arrays. There's an instruction memory array, and the data memory array. And we'll look at an example where those two things are together. But, the simple 5-stage MIPS pipeline was really designed not to have any structural hazards and the ISA was basically designed for that to be the case. But, more complex instruction sets and pipeline designs, you know, you might have to deal with something like a structural hazard. And even if with the MIPS ISA, if you go into deeper pipelines you might end up with structural hazards and, and we'll, we're going to talk about that now. Okay. So, the first thing we're going to talk about here is structural hazards if we want to unify the memory. So, as I said in the 5-stage MIPS pipeline, you have all the hardware you need for every stage, and all the stages are basically independent. But, let's say, we were going to modify this, and instead have one memory here. And we wire out, and, and we only have one port into this memory. So, only one thing can access the memory at a time. And we wire the program counter into here to [inaudible] our instructions, we wire the data out up here into the instruction register so it's just wired in the same place as the instruction memory was before. And we take the, where we had the data memory access when we want to do load a restore, and we run those wires down here. And, we put a multiplexer here to share the address and only one of these resources can use it as time. Hm. Okay, well let's draw the pipeline diagram for what happens with something, something like this hap, when, when you go to execute a load instruction, we'll say, on a unified memory architecture. So, if we take a look at this structural hazard example where we have a unified memory, where we have the one memory here which is replacing both our instruction memory, and our, our data memory. We need to do a walk through, let's use this example to walk through the pipeline diagram of how instructions will flow down, this, this example here. So, let's start off by executing something like a load first. Then, let's say, we have an add followed by an add followed by an add. Okay. So, this is our first pipeline diagram here. We're going to have the load coming down the pipe, and it's going to execute, or it's going to enter the fetch stage. Then, it's going to go into decode stage, then it's going to go into the execute stage, then it's going to go into the memory stage, and finally, write back. The first add comes down here and it's going to go into fetch. So, you go into decode, it's going to go into execute, it's going in the memory stage, and finally, go into here write back. The third add's going to come down the pipe and go into the fetch stage, decode, execute, memory, write back. So far, it looks like a pretty idealized pipeline. This next add, maybe we should just put an F here. Let's think about this, is, is this right? Can we have an add fetching from an instruction memory at the same time as a load is accessing the memory, this unified memory that we have here. And this is, this is the question. We have this unifying memory and we're trying to have two things, accessing it at the same time. And this is a structural hazard, we can't, we can't do this. So, instead, we are going to push a dash here. And we will somehow install, or bubble, or no opt, this add for cycle and we're gonna use this fetch, we're going to use the instruction memory on the subsequent cycle. And the reason we stall the add and we don't stall the load is because this is an earlier instruction than this, this is a later instruction. We want the earlier instructions to finish first.Otherwise, we might have some deadlock concerns or deadlock problems. So now, we fetch, we decode, we execute, we use the memory, and we write back. And you'll note here, this just gets pushed out one cycle because we had to stall here at the beginning one cycle. And, this memory and this point here is a structural hazard that we saw, that we had to resolve. And, in this case, let's say, we stalled one cycle to resolve that hazard. So, now that we've seen how to do a unified memory and what the pipeline should look like for that, let's go on to a different example here where we have a two cycle memory. And this two cycle memory, we're going to have stage M0 and M1. We put a pipeline register down the middle of our memory here, but only one thing is able to use that memory at a time. So let's, let's briefly draw the pipeline diagram for something like, like this. Okay. So, the second add is going to start flowing down the pipe and it's going to be in the fetch stage, decode, execute, M0, M1, write back. Then, we're going to have the load so we go fetch, decode, execute M0, M1, write back. And now, we're going to see a structural hazard. We're going to have, this second load here is going to fetch. So, I'm going to go into decode, this thing going into execute. Now, here is the problem. If we were to put M0 here, what we see is we actually have two different instructions in time waiting to use one resource, the memory. So, we need to solve this somehow. Now, how do you go about doing this? Well, there's different approaches and we'll talk about that in a minute. One approach let's say, is you could actually stall the pipeline here. So, that was one of our solutions. You stall a pipeline, so we put a dash here to mean we stalled for a cycle. And then, we're going to have M0, M1, and then write back. And you can see that it's basically pushed this instruction back one cycle, but this doesn't happen with other instructions. And the other thing to note, is that it doesn't happen if you have something like ad add after a load here, cuz that's going to go fetch, decode, execute, oh sorry, it stalls here too execute M0, M1. And these can be overlapped because we're not, we don't actually have any hazard in this case because there's not load loads or two things that are not trying to use this memory at the same time. So, you won't end up with a hazard there.