Hazard Solution 2
데이터 해저드에서 전방전달을 사용해서 해결할 수 없는 문제가 있다.
적재-사용 데이터 해저드 (load - use data hazard)
잠깐 lw 명령어의 단계를 보자.
- IF 명령어 가져와서
- ID 이를 해독 후
- EX 16비트 offset의 부호확장 + 레지스터로 주소 계산한 뒤
- MEM 그 주소의 값을 읽어서
- WB rt 레지스터에 저장한다.
그런데 이때, 만약 lw 에서 메모리 값이 로드될 레지스터를
그 다음 명령어에서 피연산자로 쓴다면?
lw 는 제일 오래 시간을 끄는 레지스터이다.
앞에서 전방전달로 해저드 해결이 가능했던 이유는
일단 필요한 값이 저장만 WB에서 될 뿐
결과는 EX단계 에서 이미 나왔기 때문인데,
lw 의 결과는 마지막 WB 단계에서 나오기 때문에
전방전달을 할 수가 없다.
따라서 눈물을 머금으며 한 사이클을 지연시킬 수 밖에 없다.
해저드 검출 유닛 (또)
ID 단계에 설치한다.
이는 lw 와 그 결과를 사용하는 명령어 사이에 거품을 넣어주기 위함이다.
즉, 명령어 해독하자마자 앞의 명령어가 lw 인지, 그 레지스터가 지금 내가 쓰려는 거랑 같은지 확인한다.
조건은 다음과 같다.
ID/EX 단계의 (즉 직전) MemRead 가 1이고 (이는 lw 일 때만 1)
직전 명령어의 rt (lw 에서 값이 저장되는 레지스터) 가 지금 명령어의 피연산자 (rs or rt) 일 때
파이프라인을 지연시킨다.
거품의 삽입
- ID 와 IF 단계의 명령어 정지
- ID 단계
PC 값 변경하지 않는다.
같은 명령어를 또 인출한다.
PCWrite 제어신호를 추가한다.
- ID 단계
- EX 단계
IF/ID 파이프라인 레지스터의 값이 바뀌지 않게 한다.
했던 거 또 한다. IF/IDWrite 제어신호 추가한다.
- 하드웨어적으로 nop 명령어 삽입
- ID/EX 파이프라인 레지스터의 제어신호 9개를 모두 0으로 한다. (어떤 레지스터도 선택 x)
RegWrite 와 MemWrite 만 0이 되면 된다.
나머지는 아무 상관 없다. (어차피 두 제어신호 때문에 값 변경되지 않음)
- ID/EX 파이프라인 레지스터의 제어신호 9개를 모두 0으로 한다. (어떤 레지스터도 선택 x)
RegWrite 와 MemWrite 만 0이 되면 된다.
- ID/EX 파이프라인 레지스터 앞에 멀티플렉서 추가
지금까지의 구조도
Hazard Detection Unit에 입력되는 선을 보면
왼쪽 두 개는 IF/ID 레지스터에서 나온 선으로, 지금 실행하려는 명령어의 피연산자 둘에서 나왔고
밑의 것은 ID/EX 레지스터에서 나온 rt 레지스터로, lw 에서 저장하게 되는 레지스터이며
오른쪽으로는 ID/EX 단계의 MemRead 이다. (이게 1이면 지금 한창 lw 명령어가 실행 중이란 뜻이다)
왼쪽 둘 중 하나가 참이고
나머지 두 선이 모두 참이라면 이는 적재 사용 해저드가 발생한 것이므로
버블을 하나 생성하여
유닛 왼쪽의 PCWrite 와 IF/ID Write 를 0으로 해서
PC도 변경 안 되게, 명령어도 다른 거 안 뽑게 하고
MUX에다가 RegWrite와 MemWrite 를 넣어서
뒤에 것이 뭐든 간에 레지스터든 메모리든 그 어떠한 것도 변경되지 않도록 한다.
파이프 라인 스케줄링으로 적재 명령어와 무관한 명령어를 배치할 수도 있지만
그럴 수 없다면 어쩔 수 없이 nop 명령어를 넣어서 지연시켜야 한다.