연산결과를 다음명령어의 Operand로 사용 혹은 memory load 데이터를 사용 할 때 발생한다.
그림에서와 같이 $t2를 계속 이어서 사용하는 구조이다.
결과는 최종적으로 5번째 wb에서 register에 저장된다
따라서 시간상으로 and 의 $t2가 2사이클 먼저 일어난다.
포워딩 로직에 맞는 control 과 mux가 들어가야한다.
포워딩을 위한 MUX
연산자와 피연산자를 비교해서 forwarding 할 데이터를 선택을 할 경우가 발생하는 선택 시그널을 각각 mux에 넣어준다. Path를 우회해서 들어가게 해주는 path를 만들어주는것이다.
이를 정리하면
1번 0 0 10
2번 00 0 10
Forwarding Unit이 원래 들어가는 경로보다 우회에서 들어가는 Path를 만들어주는것이 Fowarding 로직이다.
EXE의 결과 --> 앞에 Write Register에 쓸 결과
이 Write Register가 만약 Rs랑 같고 현재 수행하고 있는 Write Register가 디코딩에 있는 Read Register랑 같다 --> Forward A선택
이 Write Register가 만약 Rt랑 같고 현재 수행하고 있는 Write Register가 디코딩에 있는 Read Register랑 같다 --> Forward B선택
만약 두단계 차이나면 WB와 rs를 확인하고 Forward A / WB와 rt를 확인하고 Forward B
if (EX/MEM.RegWrite = ID/EX.RegisterRs) 이면
ForwardA = 10
if (EX/MEM.RegWrite = ID/EX.RegisterRt) 이면
ForwardB = 10
이는 위에서 설명한 두단계 떨어진 경우다.
(MEM/WB.RegisterRd = ID/EX.RegisterRs) 이면
ForwardA = 01
(MEM/WB.RegisterRd = ID/EX.RegisterRt) 이면
ForwardB = 01
다음과 같은 inst가 있을때,
다음과 같이 실행된다. $2, $5는 register를 통해 나와서 ALU로 향하고 있고, 2 는 MUX를 통해 EX/MEM까지 갔다.
그 다음 연산이 진행되면 2에 SUb의 결과가 적혀있고, 왼쪽의 OP가 2라는것도 알 수 있다. 따라서 두 값은 같으므로 Fowarda 10 하고 값을 Fowarding 해서 사용한다.
계산이 더 진행된후의 그림에서는 둘 다 fowarding된다.
top = 4, bottotm = 2 이다. 따라서 둘 다 fowarding 된다
한번 더 계산이 진행되었을때, 2는 이미 register first half에 들어가있다. 따라서 그대로 가져다가 쓰고, 4의 경우 exemem에서 forwarding되는 결과를 가져다가 계산에 사용한다.
로드는 명령어가 Exe Reg에 들어가지 않고 끝까지 간 후에 남는다. 따라서 lw에서는 무조건적으로 stall이 필요하다.
((ID/EX.RegisterRt = IF/ID.RegisterRs) or
(ID/EX.RegisterRt = IF/ID.RegisterRt))
--> hazard detection 한다
다음 연산에 필요한 register가 이미 앞에 lw에서 사용된 register 이면
stall and bubble한다
판단해서 만약 값이 같아서 멈처야 한다면, stall을 한다.
우선 평범하게 실행한다
그 후 lw의 target2와 다음 계산 register를 비교하고 같으면
버블을 이용해서 전부 0을 넣고 계산을 한차례 멈춘다. 연산은 이루어지지만 아무런 의미가 없다.
이런식으로 계산하던 중, Data Hazard가 발생하여 Fowarding 해준것을 알 수 있다.
명령어들은 이미 decoder 단계에서 beq, bne 인지 아닌지 같고 다름을 알 수 있다.
이 같고 다름을 따지는 로직을 decoder 단계에 넣으면 조금 성능이 향상된다.
bne beq 따지는 logic을 앞에 추가를 해서 버블을 좀더 효과적으로 파악해줄 수 있다.
다음과 같이 구성된다.
만약 beq에 걸리면 mux에 0을 넣고 bubble을 넣어준다.
따라서 다음 inst였던 add를 날리고 진행한다. (값을 전달하더라도 CS가 0이라 아무일도 일어나지 않는다.)
데이터 해저드 해결을 위한 포워딩 로직과 해저드 컨트롤로직이다. 해저드는 반드시 해결되어야 한다.
문제가 없는 경우에는 아무일없이 inst가 잘 작동하고 프로그램이 작동한다. 하지만 예외적인 상황이 발생하는경우, 예외가 발생하고 이를 처리해주어야한다.
외부이벤트이다. 네트워크, 키보드, 디스크인아웃, 타이머 등 외부장치에 의해서 발생하는 문제이다 Asynchronous이다.
내부이벤트이다. Synchronous 이다. 명령어 자체의 잘못된 수행, 혹은 fetch decode단계에서 해석 실패가 발생하는 경우이다.
현재 프로그램은 수행하다가 발생하는 순간의 이벤트
심각한 문제를 야기한다
프로그램 수행과 상관없이 외부에서 발생하는 것
하드웨어 고장을 제거하고는 대부분 cpu외 디바이스에서 발생한다
현 수행 프로그램과 관계가 없어서 다루기 쉬움
예외처리를 위한 하드웨어 로직이 들어가 있어야한다.
Page fault - fetch 오류
Misaligend mem access - 메모리영역 접근 실패할 때
Mem protect violation - 메모리 보호 침범
잘못 정의된, 혹은 잘못된 op코드
아리스메틱 오류 (0으로 나눔, 오버플로, 캐리)
오류 없음 (CPU안의 레지스터 값을 쓰는것이기 때문에 주소이상(위에서 감지함) 이 아닌이상 문제 없음)
1) stop executing the offending instruction in midstream,
2) let all preceding instructions complete,
3) flush all succeeding instructions,
4) set a register to show the cause of the exception,
5) save the address of the offending instruction, and
6) then jump to a prearranged address (the address of the exception handler code)
즉, 오류발생 시점에서 실행하고있던 inst는 끝낸 후에, 뒤에 오는 inst는 전부 날리고 handler로 jump해서 해결한다
익셉션 핸들러 : 오류 메모리를 dump 해서 유저한테 보여줌
소프트웨어에서는 이 덤프된 메모리를 가지고 보여주거나 함
OS는 일반적으로 예외발생 프로그램을 종료함
EPC
Cause
Status
cause 와 epc를 볼 수 있다.
그리고 위의 path들을 통해서 handler로 처리할 수 있다.