Chap 4. Processor

2023. 5. 26. 17:48컴퓨터구조

728x90

명령어 실행 순서

1. pc에서 명령어 메모리로 접근 , 명령어 가져옴

2. 레지스터 번호를 통해 레지스터 파일 접근-> 읽어옴

3. 명령어에 따라 달라짐

<계산 위한 ALU 사용 >

  • 산술 연산 
  • load/store 위한 메모리 주소 연산  -> load/store 위한 메모리 접근
  • Branch target 주소 연산 -> target 주소로 가거나 다음 명령어 실행 위해 PC+4

 

* Combinational element

예) AND-gate, adder, Multiplexer 등

 

*Sequential element

- 레지스터: 회로에서 계산 중간에 데이터를 저장하는 용도

Edge-triggered: 클럭이 0에서 1로 바뀔 때 값을 업데이트

-> 클럭 신호가 바뀔 때 레지스터에 보관하던 값으로 업데이트

레지스터에 쓸 때

-> write control 신호가 1일 때 clock edge에 의해 업데이트

 

The Main Control

Top 4 bit: 원래 PC

나머진 00

26 bit: 점프할 주소

 

Pipelining에 필요성

가장 오래 걸리는 작업은 load instruction

-> 이로 인해 나머지는 놀고 있게 됨. 

 

MIPS Pipeline

1. IF: 명령어 메모리로부터 명령어 fetch

2. ID: 명령어 해석 & 레지스터 읽기

3. EX: 명령에 의한 operation 실행 또는 주소 계산

4. MEM: 메모리 접근

5. WB: 결과값 레지스터에 기록

 

파이프라인 속도

-> 단계가 모두 같은 시간 걸린다면  

-> 파이프라인 아닐때 명령어 사이 시간/단계 수

*단계가 모두 같은 시간이 아니면 속도가 좀 느려지게 됨

 

Hazards

  • Structure hazards

-> 한번에 하나의 데이터를 접근 가능

-> Load/store 상태에서 데이터를 접근하고 있다면

명령어 fetch는 이번 사이클에서 할 수 없다. --> stall

-> 해결 위해 명령어 캐쉬와 데이터 캐쉬로 분리

  • Data hazard

원래 wb이후에 해야 하나 한사이클을 반으로 쪼개서 동시에 가능하게 만듦

해결책

*Forwarding: 계산이 다 되면 결과값을 레지스터에 저장할 때까지 기다릴 필요 없이

다음 명령에서 바로 사용할 수 있게 해주는 것.

-> stall을 피할 수 있다.

그러나 항상 가능하진 않다.

예) load 

* Forwarding으로 안되면 코드의 순서를 재배치하여 stall을 피한다.

-> load 명령과 두 사이클 이상은 차이 나야함.

  • Control hazard

분기 흐름의 위험

다음 명령어를 fetch하기 전에 branch 결과가 결정되야 한다.

 

*MIPS 파이프라인에서는 레지스터 비교와 target 계산을 일찍 하려고

 위에 일을 할 하드웨어를 ID stage에 추가한다.

해결책: 분기예측

branch의 결과를 예측하는 것

-> 예측이 잘못됐다면 stall

* Static branch prediction: 소프트웨어적 예측

-> loop와 if문에서의 branch 예측

Dynamic branch prediction: 하드웨어적 예측

-> 최근 히스토리 기록을 가져옴

 

 

Pipelined Datapath

흐름이 오른쪽에서 왼쪽으로 가면 hazard가 발생

-> 해결 위해 각 단계마다 레지스터를 하나씩 둬서

이전 사이클에서 생성된 값을 붙잡고 있어야 한다.

 

 

forward 해야 할 때를 어떻게 탐지할까?

*Data hazard는 언제 일어나나?

1. EX/MEM stage에서 Rd레지스터 번호와 ID/EX stage에서 Rs 또는 Rt레지스터 번호가 같을 때

-> EX/MEM 레지스터에서 forward 해야함

2. MEM/WB stage에서 Rd레지스터 번호와 ID/EX stage에서 Rs 또는 Rt레지스터 번호가 같을 때 

 

-> MEM/WB 레지스터에서 forward 해야함

 

그러나 레지스터에 값을 write 할 때만 포워딩을 해야함. write 안하면 굳이 포워딩 안해줘도 됨.

그리고 Rd레지스터 값이 0일 때는 해줄 필요없음

 

* Double Data Hazard

-> 가장 최근 값을 포워딩 해줘야 한다

 

* Load-Use Hazard는 언제 일어나나?

ID/EX 단계에서 MemRead를 할때 ID/EX 단계의 레지스터 Rt 번호와 IF/ID 단계의 레지스터 Rs 또는 Rt번호가 같을 떄

-> 이때는 포워딩이 안되므로 stall 하고 bubble 추가해야 함.

 

*어떻게 stall을 하나?

 ID/EX 레지스터에 강제로 0을 대입한다

-> EX, MEM, WB가 아무일도 하지 않도록 nop 명령 추가

 

PC값이 업데이트 되지 않도록 막는다

-> 명령이 다시 decoded 되도록 

 

 

Branch Hazrds가 일어났을 때 

브랜치된 명령어 전 명령들은 다 실행하면 안됨.

 

*브랜치 딜레이를 감소시키려면?

ID 단계로부터의  결과를 결정하기 위해 하드웨어를 이동

-> 타겟 주소 adder, 레지스터 comparator

 

*branch 명령어 2번쨰나 3번쨰 앞에 ALU 명령이 있는 경우

-> forwarding을 이용하여 해결

*branch 명령어 바로 앞에 ALU 명령이 존재하거나 

load 명령이 2번째 앞에 있는 경우

-> 한 사이클은 stall 해야 forwarding이 가능함

* branc 명령 바로 앞에 load 명령이 있는 경우

-> 두 사이클은 stall 해야 forwarding 가능

 

*분기 predictor

1-bit predictor: 과거에 taken이 맞다면 그대로 taken으로 

                                   taken이 아니였다면 not taken으로 바로 바꿈

-> 예측이 1번 틀리면 바로 바꿈.

2-bit predictor: 예측이 2번 틀려야 바꾼다. 

* 예측을 하더라도 target 주소 계산값은 1사이클 뒤에 알게 됨

-> 이를 brach target 버퍼를 통해 해결

-> 즉시 계산값을 가져올수 있다.

 

 

예외와 인터럽트

1. 종류

  • Unexpected : 순차적으로 flow가 진행되다가 갑자기 변화가 발생했을 때 
  • Exception: CPU안에서 발생
  • Interrupt: I/O 컨트롤러의 작동에 의해

 

2. MIPS에서 Exceptions Handling

(1) 원래 pc값을 EPC(Exception Program Counter)에 저장해서 돌아올 곳 저장.

(2) 어떤 문제인지 Cause register에 저장.

-> 0은 정의되지 않은 opcode일때, 1은 overflow가 났을 때

(3) 문제 원인 확인 후 해결 위한  handler로 점프

-> handler 주소는 문제에 따라 달라진다 

Undefined opcode일때 : C000 0000
Overflow일때 : C000 0020

(4) 재시작해야한다면? 

저장된 PC값으로 이동

그렇지않다면?

프로그램 종료 등.

 

*파이프라인에서 예외가 발생했을 때

add $1, $2, $1 이 명령이 EX 단계에서 overflow가 났다고 가정

-> 1. $1 값 보호

2. 이전 명령들은 정상 진행

3. add 명령과 그 다음 명령들 flush

4. Cause register, EPC 값 설정 

5. handler로 이동

(1) 재시작가능한 예외: 핸들러 실행하고 다시 원래 명령으로 이동

-> refetch하고 실행

**실제로 EPC 값으로 PC+4가 저장됨

-> 예외가 발생한 다음 명령이 실행되는 것

 

 

 

Instruction-Level Parallelism (ILP)

ILP를 증가시키기 위해 

1. Deeper pipleline( 스테이지 개수가 많은 파이프라인)

-> 스테이지 당 작업속도가 줄어듦

-> 짧은 clock cycle

 

2. Multiple issue

-> 파이프라인 stage 복사 -> 여러개의 파이프라인

-> 한 clock cycle 당 여러 명령 시작 가능

-> 더 빨리 많은 명령 가능

-> 그러나 속도가 계속 빨라지지는 않음

* Static multiple issue

  • 컴파일러가 여러 명령어들을 그룹화한다 
  • 컴파일러가 위험을 감지하고 회피한다

* Dynamic multiple issue

  • CPU가 동시에 실행 가능한 명령어들을 선발해서 내보냄
  • CPU가 위험 해결
  • 컴파일러는 명령어를 재배치하여 돕는다.

 

 

MIPS with Static Dual Issue

two-issue packets 

  • ALU/branch와 load/store을 동시에

 

Dual Issue에서의 위험

파이프라인을 병렬적으로 실행하므로 더 많은 위험 발생 가능

 

  • EX data 위험

single-issue에서는 forwarding을 사용하여 해결하지만

동시에 진행하는 거라 forwarding이 불가능

 

  • Load-use 위험

여전히 한 사이클 stall 해야함.

-> 대신 명령어 2개가 stall

 

위험피하기 위해 코드 재배치

IPC=5/4=1.25

사실상 동시에 실행할 수 있는 경우가 몇번 안되서 엄청 빨라지지 못함.

 

Loop unrolling

loop를 재구성

-> 루프 본체를 복사

복사된 루프당 서로 다른 레지스터 사용

동일한 레지스터의 load 뒤에 store

IPC=14/8=1.75

IPC가 2에 가깝지만 레지스터의 비용이 늘고, 코드 size가 커짐

728x90

'컴퓨터구조' 카테고리의 다른 글

chap 5- Memory(2)  (0) 2023.06.01
Chap 5- Memory(1)  (0) 2023.05.31
chap3 - Arithmetic for Computers  (0) 2023.04.12
컴퓨터구조 전공수업 ch02  (1) 2023.03.26
컴퓨터구조 전공수업 ch01.  (0) 2023.03.26