Pipeline
single-cycle processor는 한 사이클에 하나의 명령어를 실행
-> 프로세서 성능이 long critical path delay에 limit됨
- pipeline: 한 사이클에 이뤄졌던 걸 여러 stage로 나눔 (5개로)
한 명령어를 처리하는데 걸리는 시간은 같지만 throughput이 증가함
1) IF: Instruction Fetch, 메모리 필요
2) ID: Instruction Decode, 명령어 해석(operation, operand), 레지스터 파일 필요
3) EX: Execute, ALU 필요
4) MEM: 메모리 필요
5) WB: Write Back, 레지스터 파일 필요
쓰기는 전반부, 읽기는 후반부에 진행된다고 가정
모든 스테이지가 균형적이라면 제일 베스트!
Pipelining and ISA Design
- 모든 명령어는 32비트 -> 파이프라인에 용이
- Regular 명령어 포맷 -> R/I/J, 한 사이클안에 레지스터 읽고 해석 가능
- 메모리 접근은 load/store로만 가능
- memory operand는 메모리에 정렬되어 있음 -> 한 사이클 안에 가져올 수 있음
Hazards (다음 사이클에 다음 명령어 실행 못하는 것)
- structure hazard: 동시에 같은 자원 사용하려고 해서 충돌 발생
- data hazard: 데이터 의존성 (아직 원하는 데이터 준비 안됨)
- control hazard: 분기 명령어
Structure Hazards
동시에 같은 자원 사용하려고 해서 충돌이 일어난 것
cpu와 메모리 사이에 포트가 하나만 있다고 가정하면,
load/store 명령어는 MEM 스테이지에서 data access를 위해 메모리에 접근함
다음 다음 다음 명령어에서 IF 스테이지에서 명령어를 가져오기 위해 메모리에 접근함
-> 동시에 접근했기 때문에 IF 명령어는 stall -> 버블 발생
메모리와 cpu 사이에 명령어, 데이터를 위한 분리된 포트를 만들어서 해결!
버블: a stall initiated in order to resolve a hazard
Data Hazards
인접한 명령어의 data dependency로 발생
data is not ready for the subsequent dependent instruction
add $s0, $t0, $t1 // WB에서 $s0에 덧셈 결과가 저장됨
sub $t2, $s0, $t3 // ID에서 $s0 읽어오는데 아직 값이 반영 안됨
-> 데이터 해저드 해결하기 위해 파이프라인은 멈춰야함
WB될 때까지 기다려야함, 2개의 버블이 발생함 (성능 감소)
-> Forwarding으로 해결하자 (연산 결과를 미리 전달) !!!
EX 스테이지에서 $t0 + $t1의 연산이 완료됨, 연산 결과를 담 명령어에게 미리 전달
2개의 버블 없어도 됨~~~
하지만 forwarding으로도 완전히 해결 못하는 경우가 있음 -> Load-Use Case (버블 발생)
Hardware interlock is needed for the pipeline stall
: detect a hazard, fix the hazard
lw $s0, 8($t1) // 8($t1)의 결과를 MEM 스테이지에서 알게됨
sub $t2, $s0, $t3 // 어쩔 수 없이 한 사이클 미뤄야함 (버블 발생함)
* 스케줄링으로 버블을 숨길 수 있을 때도 있음 (항상은 x)
Control Hazards
branch 명령어와 관련 -> 참인지 거짓인지 알아야 분기 할 수 있음
- pipeline can't always fetch correct instruction
- branch instruction is still working on ID stage when fetching the next instruction
branch는 EX 스테이지 지나서야 풀리고
branch가 참일 경우 가야하는 주소도 EX 지나서야 알게됨
-> 그럼 2개의 버블이 필요함
* 2개의 버블을 1개로 줄이기 위해 ID 스테이지에 하드웨어 추가해서 비교하자!
* Delayed Branch: 다음 명령어를 항상 실행한다 -> 버블 제거할 수 있음
jal procedure // jump and link
$ra <- pc+8 (pc+4는 delay slot)
pc <- jump target
* Branch Prediction: 참 또는 거짓이라고 예측하고, 예측이 틀릴시 명령어를 flush
mips는 거짓이라고 예측한다!