add $1, $2, $3
sub $4, $1, $5
add가 $2+$3의 결과를 $1에 저장하기 전에 sub 명령어는 $1 레지스터를 사용해 버린다. 결과의 값이 저장되기 전에 레지스터를 읽으려고 하면 data hazard가 발생한다.(= 두 개의 인접 명령어에 data dependency가 있다)
1) forwarding
: write 하기 전에 write 내용이 계산되면 다음 명령어로 미리 받아온다.
add $1, $2, $3
sub $4, $1, $5
add가 $1 레지스터에 데이터를 write 하기 위해 EX 단계에서 write할 값을 계산한다. 이때, add의 WB까지 기다릴 필요 없이 add의 EX 단계에서 sub의 EX 단계로 $1 레지스터 값을 input 값으로 가져오면 된다.
lw $1, 32($6)
sub $4, $1, $5
lw가 $1 레지스터에 데이터를 저장하기 위해, MEM 단계에서 write할 값을 memory에서 가져온다. 이때, lw의 WB까지 기다릴 필요 없이 add의 MEM 단계에서 sub의 EX 단계로 $1 레지스터 값을 input 값으로 가져오면 된다.
-> stall 1번 필요(EX input 결정을 위한 추가 mux 필요, datapath 수정 필요)
2) stall(load-use data hazard의 경우)
: 앞의 명령어가 데이터를 write할 때까지, register update를 중지한다.
lw $1, 32($6)
sub $4, $1, $5
lw 명령어는 MEM에서 $1이 결정되기 때문에 stall을 써야 한다. lw가 $1 레지스터에 데이터를 write할 때까지, sub는 stall을 넣어 아무것도 하지 않은 채 기다린다.
30 add $1, $2, $3
34 beq $4, $10, 7 (target address = 34+4+28 = 66
.
.
.
66 sub $11, $22, $2
bracnh 계열 명령어는 EX에서 계산을 해야 jump할지 말지 판단한다.
1) stall
-문제 해결까지 일시 중지
2) optimized branch procesion
(1) branch가 됐는지 안 됐는지 빨리 판단하기
(2) branch할 주소를 빠르게 계산하기
-원래 MEM stage에서 branch prediction을 위한 PC 값이 정해진다.
-> next PC 값을 빠르게 결정함으로써 flush instruction 감소