Hazard Solution

2 minute read

데이터 해저드 : 전방전달 vs 지연

데이터 해저드는
앞의 명령어의 결과를 연산에 이용해야 하는데
앞의 명령어 동작이 아직 끝나지 않아서 생기는 문제이다.
이는 결과를 만들어내는 명령어의 WB 단계 이전에 ID 단계를 진행할 경우 생긴다.
그리고 이를 해결하는 방법은 파이프라인 지연과 전방전달이 있다.

예를 들어 이런 코드가 있다고 치자.

sub $2, $1, $3  
and $12, $2, $5  
or  $13, $6, $2  
add $14, $2, $2  
sw  $15, 100($2)  

1줄 :
1번 레지스터의 값에서 3번 레지스터의 값을 뺀 결과를 2번 레지스터에 저장한다.

2줄 :
2번 레지스터 값과 5번 레지스터 값의 AND 연산 후 이를 12번 레지스터에 저장해야 하나,
레지스터를 읽어올 때 지금 위에선 그제서야 연산을 하고 있을 것이다.
아직 2번 레지스터의 값이 바뀌지 않은 것이다.

3줄 :
6번 레지스터 값과 2번 레지스터 값의 OR 연산의 결과를 13번 레지스터에 저장한다.
위에선 아직 MEM 단계를 지나고 있을 것이다.

4줄 :
2번 레지스터 값 * 2를 14번 레지스터에 더해야 하는데,
2번 레지스터의 값은 지금에서야 저장될 것이다.
따라서 여기서도 2번 레지스터의 값을 특정할 수가 없다.

5줄 :
2번 레지스터에 값에서 100워드 떨어진 주소의 값을 15번 레지스터에 저장한다.
드디어 1줄의 결과로 나온 2번 레지스터 값을 쓸 수가 있다.

우리는 이렇게 앞줄의 결과가 필요하나, 아직 끝나지 않아서 그 값을 이용할 수 없을 때를
데이터 해저드라고 한다.

혹은 종속적인 두 명령어가 충분히 가까울 때에도 데이터 해저드가 나타날 수도 있다.

이를 해결하는 방법은

  1. 파이프라인 지연
  2. nop 삽입
  3. 파이프라인 스케줄링
  4. 전방전달 혹은 우회

해결 방법 1 : 파이프라인 지연

단순하게, 해저드가 해결될 때까지 파이프라인의 일부 단계를 정지시킨다.
정지한다는 것은, 그냥 그 사이클 동안 아무 일도 안 한다는 것이다.
위의 경우에서 2줄에서 아무 일도 안 하고 세 사이클 동안 가만히 있으면
1줄에서 2번 레지스터 값이 저장된 후 2줄을 안전하게 실행할 수가 있을 것이다.

이를 Pipeline Interlock 이라고 하는데,
MIPS는 Microprocessor without Interlocked Pipeline Stages 의 약자이다.
그러므로 당연히 이 방식은 사용되지 않는다.

interlocked, 아무것도 하지 않는 부분을 bubble 이라고 하는데
이는 MemWrite 나 RegWrite 을 0으로 해서 뭘 계산하든 저장을 안 하는 방식이다.

해결 방법 2 : nop 명령어 삽입

컴파일러가 종속적인 두 명령어 사이에 nop 명령어를 삽입하여 거리를 벌린다.

sub $2, $1, $3  
nop  
nop  
and $12, $2, $5  
or  $13, $6, $2  
add $14, $2, $2  
sw  $15, 100($2)  

해결 방법 3 : 파이프라인 스케쥴링

sub	$2,  $1, $3
and	$12, $2, $5
or	$13, $6, $7
add	$14, $4, $8
sw	$15, 100($9)

2줄의 명령어의 2번 레지스터에서 데이터 해저드가 발생하나,
그 밑의 3, 4번째 줄에선 그 값을 쓰지도 저장하지도 않으므로
이들과 2줄의 순서를 바꾼다.

sub	$2,  $1, $3
or	$13, $6, $7
add	$14, $4, $8
and	$12, $2, $5
sw	$15, 100($9)

이걸로 해소가 되는 경우가 많지는 않을 것 같다.

해결방법 4 : 전방전달

전방전달 (forwarding) 또는 우회 (bypass)

  • 데이터가 사용 가능하면 바로 필요로 하는 유닛
  • 레지스터에 저장할 때까지 기다리지 않고,
  • 파이프라인 레지스터에서 직접 값을 읽는다.
  • 데이터패스에 멀티플렉서와 새로운 연결 추가