Hazard 종류
- Structural hazard : same cycle에 명령어 2개 (RISCV 아키텍쳐에선 이미 이 부분은 해결)
- Data hazard : 2개의 명령어가 같은 storage(레지스터) 이용
- Control hazard : branch, jump등으로 pc address 충돌이 있는 경우
해결방법 : 무작위 stall(대기)하기, 데이터를 앞으로 땡기는 forwarding하기
Data Hazard forwarding
RISCV 아키텍쳐의 경우 5스테이지 중, 3번째 스테이지인 EX 스테이지가 되어서야 값이 계산되고 마지막 스테이지인 WB스테이지에서 값이 전달되기 때문에 같은 레지스터를 인접한 명령어끼리 중복 사용하는 경우, 제대로 된 값을 처리하지 못할 수 있다.
위 그림을 예시로 보면, sub instruction의 rd 레지스터로 x2를 사용하는데, 다음 명령어인 and와 or 또한 모두 소스 레지스터로 x2를 사용한다. 그러나, WB에서 x2의 값을 전달받기 전까지 sub값이 계산된 x2 레지스터 값을 온전히 사용하지 못한다.
따라서, cycle 낭비를 최소화 하기 위해선, 값이 계산되는 Ex stage에서 계산된 값을 바로 다음 instruction의 계산에 필요한 Ex 스테이지로 넘겨주는 forwarding 방식을 사용할 수 있다.
왼쪽 그림처럼, 각 명령어를 각각의 아키텍쳐로 생각하면 전 명령어의 Ex 결과값이, 다음 명령어의 Ex input으로 들어가는 것처럼 표현할 수 있고, 하나의 아키텍쳐로 표현하면 오른쪽 아래 그림처럼, 결과값이 되돌아가는 형태(빨간 화살표)가 된다.
다음과 같이 mem stage를 지나서 forwarding이 될 수도 있다.
그리고 이를 식으로 나타내면,
Ex/Mem에서 forwarding 되는 Ex hazard forwarding
- EX/MEM.RegisterRd = ID/EX.RegisterRs1(Rs2)
Mem/WB에서 forwarding 되는 Mem hazard forwarding
- EX/MEM.RegisterRd = ID/EX.RegisterRs1 (Rs2)
하지만 regwrite가 1이고(lw instruction), Rd register가 0이 아니어야한다.
이를 식으로 나타내면
- There is an actual register write => EX/MEM.RegWrite, MEM/WB.RegWrite
- Rd is not zero => EX/MEM.RegisterRd ≠ 0, MEM/WB.RegisterRd ≠ 0
예외사항 예시
lw x0, x1, x2
ad x10, x0, x11
> lw의 rd register이 어차피 x0 이라서 값이 0으로 고정, forwarding이 필요업슴
sw x2, 10(x3)
add x1, x2, x3
> sw는 rd가 없기에 forwarding 절대X
+ Ex hazard와 Mem hazard가 동시에 발생하는 경우 Ex hazard forwarding 진행
add $1, $1, $2
add $1, $1, $3
add $1, $1, $4
이 조건들을 다 정리하면 다음과 같이 정리할 수 있다.
◼ EX hazard
❖ if (EX/MEM.RegWrite
and (EX/MEM.RegisterRd ≠ 0)
and (EX/MEM.RegisterRd = ID/EX.RegisterRs1))
>ForwardA = 10
◼ MEM hazard
❖ if (MEM/WB.RegWrite
and (MEM/WB.RegisterRd ≠ 0)
and no EX hazard
and (MEM/WB.RegisterRd = ID/EX.RegisterRs1))
>ForwardA = 01