본문 바로가기
컴퓨터구조

컴퓨터구조 9주차

by mokhwasomssi 2021. 2. 28.

2/8 월 ~ 2/14 일 : 4시간 7분

○○●○○/○●

프로세서 부분이 내가 알고싶었던 부분이긴 한데

한줄 한줄 너무 새로운 내용이라 고통스럽다.

2/10 수 : 2시간 3분

2/14 일 : 2시간 4분


https://book.naver.com/bookdb/book_detail.nhn?bid=8751823

 

컴퓨터 구조 및 설계

이 책은 어셈블리 언어와 논리 설계에 지식이 있으면서 컴퓨터를 어떻게 설계하는지, 시스템이 어떻게 동작하는지, 왜 그 정도의 성능을 내는지를 알고 싶어 하는 사람은 물론이고, 기본적인 컴

book.naver.com


4.3 데이터패스 만들기

각 명령어들이 어떤 데이터패스 구성 요소(datapath element)들을 필요로 하는지 살펴보는 것으로 시작하자.

- 데이터패스 구성 요소 : 프로세서 안에서 데이터를 가지고 연산하거나 데이터를 저장하는 기능 유닛.

MIPS 구현에서는 데이터패스 구성 요소명령어 메모리, 데이터 메모리, 레지스터 파일, ALU, 덧셈기 등이 포함된다.


그림 4.5a : 프로그램의 명령어를 저장하고 주소가 주어지면 해당 명령어를 보내 주는 메모리 유닛

그림 4.5b : 프로그램 카운터(PC : program counter)

- 프로그램 카운터 : 프로그램에서 실행 중인 명령어의 주소를 가지고 있는 레지스터

그림 4.5c : PC를 다음 명령어 주소로 증가시키는 덧셈기

그림 4.5 명령어를 저장하고 접근하는 데 두 개의 상태소자가 필요하며,

다음 명령어의 주소를 계산하기 위해 덧셈기가 하나 필요하다.

상태소자는 명령어 메모리와 프로그램 카운터이다.


어느 명령어든지 실행하기 위해서는 메모리에서 명령어를 가져오는 것으로 시작해야 한다.

다음 명령어 실행을 준비하기 위해서 프로그램 카운터가 다음 명령어를 가리키도록 4만큼 증가시켜야 한다.

그림 4.5의 세 가지 구성 요소를 어떻게 합쳐서 명령어를 인출하고

PC를 증가시켜 다음 명령어의 주소를 구하는 데이터패스를 만드는지를 그림 4.6에 보였다.

그림 4.6 명령어를 인출하고 프로그램 카운터를 증가시키는 데

사용하는 데이터패스의 일부분


R 형식 명령어 또는 산술/논리 명령어

- 두개의 레지스터를 읽고 레지스터 내용에 ALU 연산을 수행하며 그 결과를 레지스터에 쓴다.

- add, sub, AND, OR, slt

프로세서의 범용 레지스터 32개는 레지스터 파일(register file)이라고 하는 구조 속에 들어있다.

레지스터 파일 : 접근할 레지스터 번호를 지정함으로써 읽고 쓸 수 있는 레지스터들의 집합으로 구성된 상태소자

레지스터 파일은 컴퓨터 레지스터 상태를 갖고 있다.


R 형식 명령어들은 레지스터 피연산자 세 개를 가지고 있기 때문에,

매 명령어마다 레지스터 파일에서 두 데이터 워드를 일고 데이터 워드 하나를 써야한다.

1. 레지스터에서 데이터 워드 읽기

- 레지스터 입력 1, 출력 1

- 읽을 레지스터 번호를 지정하는 입력과 레지스터에서 읽은 값을 내보내는 출력이다.

2. 레지스터에서 데이터 워드를 쓰기

- 레지스터 입력 2

- 한 입력은 쓸 레지스터 번호를 지정하고 다른 입력은 레지스터에 쓸 데이터 값을 제공한다.

레지스터 파일은 Read register 입력에 실리는 번호에 해당하는 레지스터의 내용을 항상 출력한다.

그러나 쓰기는 쓰기 제어신호에 의해 제어되므로 클럭 에지에서 쓰기가 일어나려면 이 제어 신호가 인가되어야 한다.

따라서 전체적으로 네 개의 입력(레지스터 번호용 세 개, 데이터용 한 개)과 두 개의 출력(모두 데이터용)이 필요하다.

그림 4.7a에 이를 보였다.

레지스터 번호 입력은 32개의 레지스터 중 하나를 지정해야 하므로 5비트 크기인 반면(32=25),

데이터 입력과 데이터 출력 버스는 모두 32비트 폭을 가진다.

그림 4.7b는 ALU를 보여 주고 있다.

ALU는 32비트 입력 두 개를 받아서 32비트 결과와 결과가 0인지 아닌지를 나타내는 1비트 신호를 만든다.

그림 4.7 R 형식 ALU 연산을 구현하는데 필요한 두 개의 구성 요소는 레지스터 파일과 ALU이다.

레지스터 파일은 모든 레지스터를 포함하고 있으며 읽기 포트 두 개와 쓰기 포트 하나가 있다.

레지스터 파일은 항상 Read register 입력이 지정하는 레지스터의 내용을 출력하므로 다른 제어 입력이 필요 없다.

반면에 레지스터 쓰기는 쓰기 제어신호를 인가하여 쓴다는 것을 명확히 표시하여야 한다.

쓰기는 에지 구동이기 때문에 모든 쓰기 입력(쓸 값, 레지스터 번호, 쓰기 제어신호)이

클럭 에지에서 유효해야 한다는 것을 잊지 말아야 한다.

레지스터 번호 입력은 5비트이며, 데이터 선들은 32비트이다.

ALU가 수행할 연산은 ALU operation 신호로 제어되는데 4비트이다.

분기를 구현할 때 ALU의 Zero 검출 출력을 사용하게 될 것이다.


명령어의 16비트 변위 필드 값을 32비트 부호있는 값으로 부호확장(sign-extend) 하기 위한 유닛이 필요하며

또 읽고 쓸 데이터 메모리가 필요하다.

- 부호확장 : 데이터의 크기를 증가시키기 위해 원래 데이터 값의 최상위 부호 비트를 폭이 더 큰 목적지 데이터 값의 상위 비트에 복사

따라서 데이터 메모리는 읽기/쓰기 제어신호, 주소 입력, 메모리에 쓸 데이터 입력이 필요하다

그림 4.8은 부호확장 유닛과 데이터 메모리를 보여 주고 있다.

그림 4.8 그림4.7의 레지스터 파일과 ALU 외에 적재와 저장 구현에 추가로

필요한 두 유닛은 데이터 메모리 유닛과 부호확장 유닛이다.

메모리 유닛은 입력 두 개(Address와 Write data)와 출력 한 개(Read data)를 갖는 상태소자이다.

읽기와 쓰기 제어신호가 따로 있지만 한 클럭에는 이들 중 하나만 인가될 수 있다.

레지스터 파일과는 달리 메모리 유닛은 읽기 신호가 필요하다

5장에서 보게 되겠지만 올바르지 않은 주소의 값을 읽으면 문제를 일으킨다.

부호확장 유닛은 16비트 입력을 갖고 있는데 32비트 부호있는 값으로 확장되어 출력에 나타난다.


beq 명령어는 비교할 레지스터 두 개와 16비트 변위의 세 피연산자를 갖는다.

변위는 분기 명령어 주소에 대한 상대적인 분기 목적지 주소(branch target address)를 계산하는데 사용된다.

- 분기 목적지 주소 : 분기 명령어에 의해 지정되는 주소로서 분기가 일어난다면 새로운 PC 값이 된다. MIPS 구조에서 분기 목적지는 명령어의 변위 필드 값에 분기 명령어 다음 명령어의 주소를 더한 값

명령어 형태는 beq $t1, $t2, offset 이다.

이 명령어를 구현하기 위해서는 PC 값에다 명령어 변위 필드의 부호확장 값을 더해서 분기 목적지 주소를 계산해야 한다.

분기 명령어의 정의에는 우리가 주의를 기울여야 하는 두 가지 점이 있다.

1. 명령어 집합 구조는 분기 주소 계산의 베이스 주소가 분기 명령어 다음 명령어의 주소라고 서술하고 있다.

명령어 인출 데이터패스에서 PC+4(다음 명령어의 주소)를 계산하기 때문에

이 값을 분기 목적지 주소 계산의 베이스로 사용하는 것이 편하다.

2. 구조는 또한 변위 필드는 2비트만큼 왼쪽 자리이동하여 워드 변위가 된다고 서술한다.

이렇게 함으로써 변위 필드의 유효 범위를 4배만큼 증가시킨다.

분기 목적지 주소를 계산하는 것 외에 실행할 다음 명령어가 뒤어 있는 명령어가 될지

아니면 분기 목적지 주소에 있는 명령어가 될지를 판단해야 한다.

1. 분기가 일어났다(branch taken)

분기 조건이 충족되어서 분기 목적지 주소가 PC 값이 된다

2. 분기가 일어나지 않았다(branch not taken)

분기 조건이 거짓이어서 분기 명령어 다음에 나오는 명령어의 주소가 PC 값이 된다.


따라서 분기 데이터패스는 분기 목적지 주소를 계산하고 레지스터 내용을 비교하는 두 가지 일을 해야 한다.

분기를 다루는 데이터패스 부분을 그림 4.9에 보였다

분기 목적지 주소를 계산하기 위해서 분기 데이터패스는 부호확장 유닛과 덧셈기를 포함한다.

비교를 수행하기 위해서는 레지스터 파일과 ALU가 필요하다.

점프 명령어는 명령어의 하위 26비트를 2비트만큼 왼쪽으로 자리이동한 값으로 PC의 하위 28비트를 대체한다.

그림 4.9 분기 명령어를 위한 데이터패스는 ALU를 사용하여 분기 조건을 계산하고

별도의 덧셈기를 사용하여 분기 목적지 주소를 계산한다.

분기 목적지 주소는 증가한 PC 값과 명령어의 하위 16비트(분기 변위)를 부호확장하고

왼쪽으로 2비트 자리이동한 값의 합이다.

제어 논리회로는 ALU의 Zero 출력을 보고 증가된 PC 값과 분기 목적지 주소 중 어느 쪽이 PC에 들어가야 하는지를 결정한다.


단일 데이터패스 만들기

이제까지 각각의 명령어 종류에 필요한 데이터패스 구성 요소에 대하여 알아보았다.

이제는 이 데이터패스 구성 요소들을 하나로 묶고 여기에 제어를 첨가함으로써 구현을 완성하고자 한다.

가장 간단한 데이터패스는 모든 명령어를 한 클럭 사이클에 실행하도록 시도하는 것이다.

이것은 어느 데이터패스 자원도 명령어당 두 번 이상 사용될 수 없음을 의미한다.

따라서 두 번 이상 사용할 필요가 있는 구성 요소는 필요한 만큼 여러 개를 두어야 한다.

그러므로 데이터 메모리와는 별도로 명령어 메모리가 필요한 것이다.

몇몇 기능 유닛은 복제할 필요가 있지만, 많은 구성 요소들은 서로 다른 명령어 흐름들이 공유하여 사용할 수 있다.

두 개의 다른 명령어 종류들이 데이터패스 구성 요소를 공유하기 위해서는 그 구성 요소의 입력에 여러 개의 연결을 허용해야 하며,

멀티플렉서와 제어신호를 사용해서 그 입력들 중 하나를 선택해야 한다.


예제 : 데이터패스 구축

산술/논리(R 형식) 명령어 데이터패스와 메모리 명령어 데이터패스는 매우 비슷하나 다음과 같은 점이 다르다.

1. 둘 다 ALU 사용

- R형식 명령어 : 입력은 두 레지스터에서부터 옴

- 메모리 명령어 : 주소를 계산하기 위해여 ALU 사용, 두 번째 입력은 명령어의 16비트 변위 필드를 부호확장한 값

2. 목적지 레지스터에 저장되는 값

- R형식 명령어 : ALU에서 옴

- 적재 명령어 : 메모리에서 옴

메모리 참조 명령어와 산술/논리 연산 명령어를 실행하는 데이터패스 만들기

- 레지스터 파일 하나, ALU 하나 사용

- 멀티플렉서 마음껏 사용 가능

ALU 입력에 멀티플렉서 하나

레지스터 파일의 데이터 입력에 멀티플렉서 하나를 설치

그림 4.10 메모리 명령어와 R 형식 명령어를 위한 데이터패스

그림 4.7과 4.8의 데이터패스에 멀티플렉서를 추가하여 어떻게 단일 데이터패스를 만드는지 보여 주고 있다.


앞에서 살펴본 데이터패스를 합쳐서 MIPS 구조를 위한 단순화된 데이터패스를 만들 수 있다.

1. 명령어 인출을 위한 데이터패스(그림 4.6)

2. R 형식 명령어와 메모리 명령어를 위한 데이터패스(그림 4.10)

3. 분기 명령어를 위한 데이터패스(그림 4.9)

그림 4.11 MIPS 구조를 위한 단순한 데이터패스는 서로 다른 명령어 종류가 사용하는 구성 요소들을 합친 것이다.

이 데이터패스는 기본 명령어들(적재/저장, ALU 연산, 분기)을 한 클럭 사이클에 실행할 수 있다.

점프 명령어를 지원하는 부분은 나중에 추가


4.4 단순한 구현

4.3절의 데이터패스에 단순한 제어기능을 추가하여 단순한 구현을 만들고자 한다.

워드 적재(lw), 워드 저장(sw), 같을 시 분기(beq), 산술/논리 연산 명령어(add, sub, AND, OR, set on less than)을 포함한다.

차후에 점프 명령어(j)를 포함하도록 설계를 확장할 예정이다.


ALU 제어

MIPS ALU는 제어 입력 4개를 사용하는 다음 6개 조합을 정의하고 있다.

워드 적재, 워드 저장 명령어인 경우에는 메모리 주소를 계산하기 위한 덧셈용으로 ALU 사용

R 형식 명령어의 경우에는 명령어 하위 비트의 기능 필드 값에 따라서 5가지 연산(AND, OR, add, subtract, set on less than)중 하나

같을 시 분기 명령어의 경우에 ALU는 뺄셈을 수행

명령어의 기능 필드와 2비트 제어 필드(ALUOp)를 입력으로 갖는 조그만 제어 유닛을 만들어서

4비트 ALU 제어 입력을 발생시킬 수 있다.

ALUOp가 표시해야 될 연산은

1. 적재와 저장의 경우에는 덧셈(00)

2. beq의 경우에는 뺄셈(01)

3. 산술/논리 연산의 경우에는 기능 필드에서 나타내는 연산(10)


그림 4.12는 2비트 ALUOp 제어와 6비트 기능 코드를 사용하여 어떻게 ALU 제어 입력을 만드는지 보여준다.

그림 4.12 ALU 제어 비트들은 ALUOp 제어 비트와 R 형식 명령어의 기능 코드 값에 의해 결정된다.

첫 번째 열에 나열된 opcode가 ALUOp 비트 값을 결정한다.

ALUOp 값이 00이나 01일 때 해당 ALU 동작은 기능 코드 필드에 영향을 받지 않는다.

ALUOP가 10일 때는 기능 코드 값이 ALU 제어 입력을 결정한다.

주 제어 유닛이 ALUOp 비트를 생성하고 ALU 제어 유닛은 이것을 입력으로 받아서

ALU를 제어하는 실제 신호를 만들어 내는 이런 다단계 디코딩은 많이 쓰이는 구현 기법이다.

다단계 제어를 사용하면 주 제어 유닛의 크기를 줄일 수 있다.

또한 여러 개의 작은 제어 유닛을 사용하는 것은 제어 유닛의 속도를 증가시킬 수도 있다.


2비트 ALUOp 필드와 6비트 기능 필드를 4비트의 ALU 연산 제어 비트로 구현하는 방법에는 여러 가지가 있다.

기능 필드가 가질 수 있는 값 64개 중에서 겨우 몇 개만이 사용되고 그것도 ALUOp 비트가 10일 때만 사용하기 때문에,

가능한 값들 중에서 일부만을 사용하여 ALU 제어 비트를 만들어내는 조그만 논리회로를 사용할 수 있다.

이 논리회로를 설계하는 단계로서 기능 코드 필드의 관심 있는 값들과 ALUOp 비트에 대한 진리표를 만드는 것이 도움이 된다.

이것을 그림 4.13에 보였다.

이 진리표(truth table)는 이 같은 두 가지 입력 필드 값에 따라 4비트 ALU 제어 값이 어떻게 설정되는지를 보여 주고 있다.

- 진리표 : 입력이 가질 수 있는 모든 값을 나열하고 각 경우의 출력 값을 보이는 논리 연산 표현 방법

그림 4.13 4비트 ALU 제어신호(Operation이라 불림)를 위한 진리표.

입력은 ALUOp와 기능 코드 필드이다.

ALU 제어가 인가되어야 하는 엔트리만을 보였다. don't care 항들이 몇 개 늘어났다.

예를 들어 ALUOp는 입력값 11을 사용하지 않는다. 따라서 진리표에서 10과 01대신 1X와 X1를 사용할 수 있다.

또 기능 필드가 사용되는 경우(R 형식 명령어) 이 필드의 첫 두 비트(F5와 F4)는 항상 10이다.

따라서 그들은 don't care 항들이고 진리표에서 XX로 표시된다.


주 제어 유닛의 설계

그림 4.11의 데이터패스에 필요한 명령어 필드와 제어선들을 알아내는 것으로 시작하자

명령어 필드들을 데이터패스에 연결하는 방법을 이해하기 위해서는 세 가지 명령어 종류,

즉 R 형식 명령어, 분기 명령어, 적재/저장 명령어 종류의 형식을 다시 살펴보는 것이 효과적일 것이다.

이들 명령어 형식은 그림 4.14에 나타나 있다.

그림 4.14 세 가지 명령어 종류는 두 가지 명령어 형식을 사용한다.

몇 가지 눈여겨볼 점

1. opcode라 불리는 op필드는 항상 비트 31:26에 포함된다. 이 필드를 Op[5:0]라고 부른다.

- opcode : 명령어의 연산과 형식을 나타내는 필드

2. 읽을 레지스터 두 개는 항상 rs[25:21], rt[20:16] 필드에 의해 지정된다 : R형식 , 같을 시 분기, 저장 명령어

3. 베이스 레지스터는 항상 rs[25:21] : 적재/저장 명령어

4. 16비트 변위는 항상 address[15:0] : 같을 시 분기, 적재/저장 명령어

5. 목적지 레지스터는 두 곳 중 하나에 있다.

적재 명령어에서는 비트 20:16(rt)에 있고 R형식 명령어에서는 비트 15:11(rd)에 있다.

따라서 쓰기가 행해질 레지스터 번호로 명령어의 어느 필드를 사용할지 선택하기 위하여 멀티플렉서를 추가해야 한다.