의존성은 Data / Control Hazard 발생시킴
* Data Hazard 해결 방법
- nop 집어넣기 (0x00000000) -> 해저드 해결되지만 느려짐
- 코드 스케줄링으로 해결 가능할 수도 있음
- Forwarding (레지스터 파일에 써질 때까지 기다리지 않음)
Forwarding
* 이전 명령어
1a. EX/MEM.RegisterRd = ID/EX.RegisterRs
1b. EX/MEM.RegisterRd = ID/EX.RegisterRt
EX hazard:
if (EX/MEM.RegWrite // Reg에 진짜 쓰냐
and (EX/MEM.RegisterRd != 0) // Rd가 0번이 아니냐
and (EX.MEM.RegisterRd = ID/EX.RegisterRs)) ForwardA = 10
// Rs랑 같으면 ForwardA를 10으로 설정
if (EX/MEM.RegWrite // Reg에 진짜 쓰냐
and (EX/MEM.RegisterRd != 0) // Rd가 0번이 아니냐
and (EX.MEM.RegisterRd = ID/EX.RegisterRt)) ForwardB = 10
// Rt랑 같으면 ForwardB를 10으로 설정
* 이전이전 명령어
2a. MEM/WB.RegisterRd = ID/EX.RegisterRs
2b. MEM/WB.RegisterRd = ID/EX.RegisterRt
MEM hazard:
if (MEM.WB.RegWrite // Reg에 진짜 쓰냐
and (MEM.WB.RegisterRd != 0) // Rd가 0번이 아니냐
// EX hazard가 아니라는 조건 추가해야함
and not(EX/MEM.RegWrite and (EX/MEM.RegisterRd !=0)
and (EX/MEM.RegisterRd = ID/EX.RegisterRs))
and (MEM.WB.RegisterRd = ID/EX.RegisterRs)) ForwardA = 01
// Rs랑 같으면 ForwardA를 01로 설정
if (MEM.WB.RegWrite // Reg에 진짜 쓰냐
and (MEM.WB.RegisterRd != 0) // Rd가 0번이 아니냐
// EX hazard가 아니라는 조건 추가해야함
and not(EX/MEM.RegWrite and (EX/MEM.RegisterRd !=0)
and (EX/MEM.RegisterRd = ID/EX.RegisterRt))
and (MEM.WB.RegisterRd = ID/EX.RegisterRt)) ForwardB = 01
// Rt랑 같으면 ForwardB를 01로 설정
ALU 소스 받아들일 때 data hazard 감지해야 한다!
data hazard 감지하면 forwarding 한다!
Load-Use Case, Hazard Detection Unit
Load-Use Case는 여전히 해저드 발생시킴
그래서 hazard detection unit은 load-use 찾고, stall까지 해줘야함
1) Load-Use Case Hazard Detect
2) decode 단계까지 가져온 명령어를 nop 시킨다
3) 갖고온 명령어부터 모든 명령어를 하나씩 미룬다
if (ID/EX.MemRead and // 바로 앞에 명령어가 load!
((ID/EX.RegisterRt = IF/ID.RegisterRs) or // lw는 I-type 명령어 -> 목적지가 Rt
(ID/EX.RegisterRt = IF/ID.RegisterRt)))
stall the pipeline
Control Hazards - Branch
조건 참, 거짓 여부 판별 / 타겟 주소 계산 필요함
brnach는 MEM 스테이지에서 풀린다 -> 3사이클 penalty + flush 필요
무조건 거짓이라고 예측하고 동작함 -> 만약 참이라고 판별되면 flush하고 분기
이걸 1사이클 penalty로 바꾸기 위해서 조건 비교, 타겟 주소 계산하는걸 다 ID로 끌고옴
그리고 IF.flush 시그널을 IF/ID 파이프라인 레지스터에 추가한다 (for 파이프라인 무효화)