Unexpected Events in pipeline
예상치 못한 이벤트는 크게 두 종류로 나눌 수 있습니다:
- Exception: CPU 내부에서 발생하는 event입니다. 예를 들어 정의되지 않은 명령어 코드(undefined opcode), overflow, syscall 등이 있습니다.
- Interrupt: 외부 I/O controller에 의해 발생합니다.
이러한 예상하지 못한 이벤트들은 control flow를 바꾸며, 성능 손실 없이는 처리하는 것이 어렵습니다. 즉, stall이 필요합니다. 이때 고려해야하는 점은 pipeline의 모든 명령들을 stop할 수는 없으니 문제가 되는 부분만 stop해야하는데 이를 어떻게 하는지 입니다.
Two types of exceptions
- Interrupt - interrupt는 프로그램 실행과 비동기적으로 발생합니다. 이는 external event에 의해 발생하며, pipeline에서 현재 실행중인 명령어들이 완료된 후 OS interrupt handler에게 control을 넘겨 처리될 수 있습니다. user program은 단순히 일시 중지되었다가 재개될 수 있습니다. *이는 external event에 의해 발생하는 것이기 때문에 instr. 자체에는 문제가 없습니다. 따라서 다시 돌아와서 instr.들을 재개해도 문제가 발생하지 않습니다.
- Exception(Traps) - Trap은 프로그램 실행과 동기적으로 발생합니다. 이는 internal event에 의해 야기되며, 문제가 발생한 instr. 처리 도중에 pipeline을 멈추고 OS의 trap handler에게 control을 넘겨야합니다. 문제가 된 instr.은 재시도 되거나 중단될 수 있습니다. *Exception은 pipeline 안에 있는 instr. 자체에 문제가 있는 것이기 때문에 trap handler에 의해 instr. 의 문제가 해결되지 않는다면 다시 돌아와 재개할 수 없습니다. 즉, abort됩니다.
Dealing with Exception
Exception은 또 다른 형태의 control hazard입니다. exception은 다음과 같은 상황에서 발생할 수 있습니다:
- R-type arithmetic overflow
- undefined opcode
- I/O device request
- OS service request (e.g., page fault, TLB exception)
- Hardware malfunction
Exception 발생 시 pipeline은 다음과 같은 작업을 수행합니다.
(1) 오류를 일으킨 명령어의 중간 실행을 중지합니다.
(2) 해당 명령어 이전의 모든 명령어들은 완료되도록 합니다.
(3) 해당 명령어 이후의 모든 명령어들은 flush합니다.
(4) 예외의 원인을 나타내는 Cause register를 설정합니다.
(5) 오류를 일으킨 명령어의 주소를 EPC register에 설정합니다.
(6) 그리고 미리 정해진 주소(exception handler address)로 jump합니다.
Handling Exceptions
MIPS에서 exception은 System Control Coprocessor (CP0)에 의해 관리됩니다. 오류를 일으키거나 interrupt된 명령어의 PC값은 EPC (Exception Program Counter) register에 저장됩니다. 또한 문제의 원인에 대한 정보는 Cause reigster에 저장됩니다. 이후 service handler의 주소로 jump하여 예외 처리를 시작합니다.
이때 Vectored Interrupt라는 방식을 사용할 수 있습니다. 이는 예외의 원인에 따라 handler address가 결정되는 방식으로, handler는 interrupt를 직접 처리하거나 실제 handler로 jump할 수 있습니다.
Handler actions
handler는 Cause register를 읽어 관련 handler로 이동하고 필요한 조치를 결정합니다. 만약 exception이 restartable한 경우 handler는 수정 조치를 취하고 EPC register에 저장된 주소를 사용하여 프로그램으로 복귀합니다. 하지만 restartable하지 않은 경우 프로그램을 종료하고 EPC, Cause 등의 정보를 사용하여 오류를 보고합니다.
예를 들어 EX단계에서 발생하는 add 명령어(add $1, $2, $1)의 overflow의 경우 (1) 우선 결과가 저장될 regiser $1에 덮어쓰이지 않도록 방지해야하며, (2) 이전 명령어들은 완료되도록 합니다. (3) overflow가 발생한 add 명령어와 그 이후 명령어들을 flush합니다. (4) Cause, EPC register값을 설정한 후 handler로 control을 설정합니다.
이는 misprediction branch 처리와 유사하며, ID.Flush, EX.Flush hardware unit 등이 추가로 필요합니다. 이를 고려하면 다음과 같은 data path가 만들어집니다:
Exception Properties
Restartable exception은 pipeline이 해당 명령어를 flush하고, handler가 실행된 후, 해당 명령어는 처음부터 다시 fetch되어 실행됩니다. 이때 PC값은 EPC register에 저장되어 오류를 유발한 명령어를 이용합니다.
하지만, MIPS에서는 실제 오류 발생 명령어의 PC값이 아닌 PC+4 값이 저장되기 때문에 handler는 이를 고려하여 프로그램으로 복귀해야합니다.
Additions to MIPS to Handle Exceptions
다음은 MIPS에서 exception을 handling하기 위해 필요한 hardware입니다:
- Cause register: 예외를 기록하는 hardware이며, 쓰기를 제어하는 CauseWrite signal이 있습니다.
- EPC register: 오류를 일으킨 명령어 주소를 기록하는 hardware이며, 쓰기를 제어하는 EPCWrite signal이 있습니다.
- PC MUX: exception handler address를 PC에 추가하기 위해 PC 입력 MUX를 확장하여 handler address를 새로운 입력으로 추가합니다.
- Flush: 오류를 일으킨 명령어와 그 이후 명령어들을 flush하는 방법이 필요합니다.
Multiple simultaneous exceptions
pipelining은 동시에 여러 명령어를 중첩하여 실행하기 때문에 Multiple simultaneous exception이 가능합니다. 가장 간단한 해결 방법은 가장 먼저 발생한 명령어의 exception부터 처리하는 것입니다. 이를 위해 이후 명령어들을 flush하는 방식을 precise exception이라고 부릅니다. 하지만 복잡한 pipeline(예: 한 cycle에 여러 instructions들이 issue가 생기는 경우, 순서에 상관없이 완료되는 pipeline)에서는 precise exception을 유지하는 것은 어렵습니다.
Imprecise Exceptions
이 방식은 단순이 pipeline을 멈추고 상태(Cause)를 저장합니다. 어떤 명령어에서 exception이 발생했는지, 그리고 어떤 명령어를 완료하고 flush를 해야하는지는 handler software가 직접 처리합니다. 이는 hardware를 단순화 시키지만, software가 매우 복잡해지는 결과를 낳습니다. 하지만 이 역시 complex multiple-issue나 out-of-order pipeline에서는 비현실적인 해결책입니다. 따라서 현대의 processor는 precise exception으로 처리합니다.