본문 바로가기
컴퓨터구조

컴퓨터구조 8주차

by mokhwasomssi 2021. 2. 18.

2/1 월 ~ 2/7 일 : 6시간 26분

○○●○●●●

2/3 수 : 2시간 9분

2/5 금 : 2시간

2/6 토 : 2시간 1분

2/7 일 : 16분

4장 프로세서부터는 한줄한줄 다 모르는 내용이라 요약을 못하겠다.


 

 

그림 3.14 부동소수점 덧셈

3.15 부동소수점 덧셈 전용 산술 유닛의 블록 다이어그램

먼저 어느 지수가 얼마나 큰가를 알아보기 위해 작은 ALU로 두 지수를 뺀다.

이렇게 계산된 차이는 세 개의 멀티플렉서를 제어한다.

가장 왼쪽 멀티플렉서는 큰 지수를 선택하고,

가운데 것은 작은 수의 유효자리,

가장 오른쪽 멀티플렉서는 큰 수의 유효자리를 선택한다.

작은 유효자리는 오른쪽으로 자리이동된 후 큰 ALU에서 큰 수의 유효자리와 더해진다

정규화 단계는 합을 왼쪽이나 오른쪽으로 자리이동시키면서 지수를 증가시키거나 감소시킨다.

자리맞춤 단계에서 최종 결과가 생선된다.

부동소수점 곱셈

과학적 표기법의 십진수 곱셈을 직접 손으로 해 보자

( 1.100ten X 1010 ) X ( 9.200ten X 10-5 )

유효자리에는 네 자리, 지수에는 두 자리까지 저장할 수 있다고 가정한다.

단계 1. 지수를 더하기만 하면 곱의 지수를 구할 수 있다.

새로운 지수 = 10 + (-5) + 127 = 132

단계 2. 유효자리의 곱셈

각 피연산자의 소수점 오른쪽에 세자리 수가 있다.

따라서 결과의 오른쪽으로부터 여섯 번째 자리에 소수점을 찍는다.

단계 3. 이 곱은 비정규화되어 있으므로 알맞게 고칠 필요가 있다.

곱셈 후의 결과를 오른쪽으로 한자리 자리이동하고,

지수에는 1을 더한다.

이 시점에서 오버플로와 언더플로를 검사할 수 있다.

단계 4. 유효자리 네 자리로 자리맞춤

단계 5. 결과의 부호는 피연산자의 부호에 의존한다.

부호가 같으면 결과의 부호는 양수이고 그렇지 않으면 결과는 음수이다.

그림 3.16 부동소수점 곱셈

MIPS의 부동소수점 명령어

MIPS는 다음과 같은 명령어를 사용하여

IEEE 754 단일 정밀도 및 2배 정밀도 표현 형식을 지원한다.

그림 3.17 지금까지 나온 MIPS 부동소수점 아키텍처


[하드웨어 소프트웨어 인터페이스]

컴퓨터 설계자가 부동소수점 연산 지원과 관련하여 부딪치는 문제 중 하나는

정수 명령어가 사용하는 레지스터를 같이 사용할 것인지

아니면 부동소수점 전용의 특별 레지스터를 추가할 것인지 하는 것이다.

프로그램이 정수 연산을 할 때와 부동소수점 연산을 할 때는 보통 다른 데이터를 사용하므로,

레지스터를 분리하면 프로그램 수행에 필요한 명령어의 수가 약간 증가할 뿐이다.

정작 크게 영향을 받는 부분은 부동소수점 레지스터와 메모리 사이의

데이터 이동에 사용할 별도의 데이터 전송 명령어들을 만들어야 한다느 것이다.

별도의 부동소수점 레지스터를 사용하는 것의 장점은

1. 명령어 형식의 비트 수를 늘리지 않고도 두 배나 많은 레지스터를 사용할 수 있다.

2. 정수 레지스터와 부동소수점 레지스터가 따로 있으니 레지스터 대역폭이 두 배로 늘어난다.

3. 부동소수점에 맞게 레지스터를 특화시킬 수 있다.


정확한 산술

가장 작은 수와 가장 큰 수 사이의 모든 수를 정확하게 나타낼 수 있는 정수와는 달리,

부동소수점 숫자는 실제로 나타낼 수 없는 수의 근삿값인 것이 보통이다.

우리가 할 수 있는 최선의 방법은 실제의 수에 가장 근접한 부동소수점 표현을 구하는 것이고

이를 위해 IEEE 754는 프로그래머가 원하는 근사 방법을 선택할 수 있도록 여러 가지 자리 맞춤 방법을 제공한다.

정확하게 자리맞춤을 하기 위해서는

계산 시에 하드웨어가 중간 결과를 저장하는 추가 비트를 포함해야 한다.

- 자리 맞춤 : 부동소수점의 연산의 중간 결과가 부동소수점 형식에 일치하도록 하는 방법

부동소수점 형식으로 나타낼 수 있는 가장 가까운 수를 찾아내는 것이 목적이다.

- 보호 비트 : 부동소수점 계산 도중에 오른쪽에 유지되는 두 추가 비트

자리 맞춤의 정확도를 개선하기 위해 사용한다.

자리맞춤 시 최악의 경우는 실제 값이 두 부동소수점 표현의 중간이 될 때이다.

부동소수점에서 정확도는 유효자리의 최하위 비트 중 오류가 발생한 것이 몇 비트인가에 따라 결정된다.

이 척도를 ulp (units in the last place)라고 부른다. ​

- ulp : 실제 수와 표현 가능한 수의 최하위 유효자리 비트 중에 서로 다른 비트의 개수


요약

이 절은 컴퓨터 연산은 유한하고 따라서 실제 연산과 일치하지 않을 수 있다는 것을 보여준다.

예를 들어 IEEE 754 표준 부동소수점 표현은 언제나 실제 수의 근삿값이다.

(-1)S X (1 + Fraction) X 2(Exponent - Bias)

컴퓨터 시스템은 컴퓨터 연산과 실제 연산 사이의 이러한 차이를 최소화하는 데 주의하여야 하며,

프로그래머도 이러한 근사화에 관련되는 내용을 알고 있어야만 한다.


3.6 병렬성과 산술연산 : 서브워드 병렬성

128비트 덧셈기 내부의 올림수 체인을 분할하면 프로세서가 병렬성을 활용해서,

8비트 피연산자 16개나 16비트 피연산자 8개, 32비트 피연산자 4개, 또는 64비트 피연산자 두 개를 동시에 연산할 수 있다.

큰 워드 내부에 병렬성이 있다고 할 때, 이것의 확장을 서브워드 병렬성이라고 한다.

더 일반적인 이름으로 데이터 수준 병렬성, 벡터 또는 SIMD(single instruction, multiple data)라고도 한다.

멀티미디어 응용이 많아지면서 작은 데이터에 대한 병렬 연산을 지원하는 산술 명령어가 등장하게 되었다.


4. 프로세서

4.1 서론

1장에서 컴퓨터 성능은 세 가지 주요 요인,

즉 명령어 개수, 클럭 사이클 시간, 명령어당 클럭 사이클 수(CPI)에 의해 결정된다는 것을 알았다.

2장에서 살펴본 바와 같이 컴파일러와 명령어 집합 구조가 프로그램에 필요한 명령어 개수를 결정한다.

그러나 클럭 사이클 시간과 명령어당 클럭 사이클 수는 프로세서의 구현 방법에 따라 결정된다.

이 장에서는 MIPS 명령어 집합을 두 가지 다른 방법으로 구현하여 데이터패스와 제어 유닛을 완성시키려 한다.

이 장은 프로세서를 구현하는 데 사용되는 원리와 기법들에 대한 설명을 포함하고 있다.

이 절에서는 매우 추상적이고 단순한 개괄을 서술하며,

다음 절에서는 데이터패스를 만들고 MIPS 같은 명령어 집합 구현에 충분한 프로세서의 간단한 버전을 구성한다.

이 장은 많은 부분을 조금 더 현실적인 파이프라인 MIPS 구현에 할애하고,

마지막으로 x86과 같이 좀 더 복잡한 명령어 집합을 구현하는 데 필요한 개념들을 설명한다.


기본적인 MIPS 구현

핵심적인 MIPS 명렁어 집합의 부분집합을 구현할 것인데, 그 부분집합은 다음과 같다.

- 메모리 참고 명령어인 워드 적재(lw)와 워드 저장(sw)

- 산술/논리 명령어인 add, sub, AND, OR, slt

- 같을 시 분기 명령어인 beq와 점프 명령어 j

이 정도 명령어로도 데이터패스와 제어 유닛을 설계하는 데 사용되는 핵심 원리는 설명될 수 있다.

이 구현을 살펴보면서 명령어 집합 구조가 구현의 여러 가지 측면을 어떻게 결정하는지,

또 여러 가지 구현 전략이 클럭 속도와 CPI에 어떻게 영향을 미치는지 살펴 볼 기회를 갖게 될 것이다.


구현에 대한 개요

2장에서 정수형 산술/논리 명령어, 메모리 참조 명령어, 분기 명령어를 포함하는 핵심적인 MIPS 명령어를 살펴보았다.

이러한 명령어 구현에 필요한 일의 상당히 많은 부분은 명령어 종류에 상관없이 동일하다.

어떤 명령어든지 처음 두 단계는 다음과 같이 모두 동일하다.

1. 프로그램 카운터(PC)를 프로그램이 저장되어 있는 메모리에 보내어 메모리로 부터 명령어를 가져온다.

2. 읽을 레지스터를 선택하는 명령어 필드를 사용하여 하나 또는 두 개의 레지스터를 읽는다.

이 두 단계 이후에 명령어 실행을 끝내기 위해 필요한 행동들은 명령어 종류에 따라 달라진다.

다행히도 세 가지 명령어 종류(메모리 참조 명령어, 산술/논리 명령어, 분기 명령어) 각각에 대해서는

명령어가 무엇인지에 상관없이 필요한 행동들이 대부분 같다.

MIPS 명령어 집합의 단순함과 규칙적인 특성이 많은 종류의 명령어 실행을 비슷하게 만들어 줌으로써 구현을 단순화한다.

예를 들면 점프 명령어를 제외한 모든 명령어 종류가 레지스터를 읽은 후에는 ALU를 사용한다.

메모리 참조 명령어는 주소 계산을 위해,

산술/논리 명령어는 연산을 수행하기 위해,

분기 명령어는 비교하기 위해여 사용한다.

ALU를 사용한 후에는

메모리 참조 명령어는 메모리에 접근

산술/논리 명령어와 적재 명령어는 ALU나 메모리에서 온 데이터를 레지스터에 쓰기

분기 명령어는 비교 결과에 따라서 다음 명령어의 주소를 바꾸거나 PC값을 4만큼 증가


그림 4.1 MIPS 부분집합 구현의 추상적 개관.

주요 기능 유닛과 그들 사이의 연결을 보여 주고 있다.

모든 명령어의 실행은 PC를 사용하여 명령어 메모리에 명령어 주소를 보내는 것으로 시작된다.

명령어를 가져온 후에는 명령어의 필드를 보면 명령어가 사용하는 레지스터 피연산자를 알 수 있다.

레지스터 피연산자를 읽어 오면,

메모리 주소를 계산하기 위하여(적재나 저장 명령어의 경우),

산술연산의 결과를 구하기 위하여(정수 산술/논리 명령어의 경우),

또는 비교하기 위하여(분기 명령어의 경우) 피연산자들을 연산할 수 있다.

산술/논리 명령어이면 ALU 결과를 레지스터에 쓴다.

적재나 저장 명령어이면 ALU 결과를 메모리 주소로 사용하여 레지스터 값을 저장하거나 레지스터에 적재할 값을 읽어 온다.

ALU나 메모리에서 나온 결과는 레지스터 파일에 넣는다.

분기 명령어의 경우는 ALU 출력을 사용하여 다음 명령어 주소를 결정한다.


그림 4.1은 MIPS 구현을 상위 수준에서 본 그림으로서, 여러 기능 유닛과 그들 사이의 연결에 초점을 맞추고 있다.

프로세서 내의 데이터 흐름을 거의 다 보여 주고 있지만 명령어 실행에 중요한 두 가지 측면이 빠져있다.

1. 서로 다른 근원지에서 나온 데이터가 같은 유닛으로 가는 곳이 몇 군데 있다.

PC에 들어갈 값은 두 덧셈기 중 하나에서 나오고

레지스터 파일에 쓰일 데이터는 ALU나 데이터 메모리에서 나오며

ALU의 두 번째 입력은 레지스터나 명령어의 수치 필드에서 나온다.

그러므로 다수의 근원지 중에서 하나를 선택하여 그것만을 목적지로 보내는 구성요소를 추가하여야 한다.

이 같은 선택은 일반적으로 멀티플렉서(multiplexor)라 불리는 소자를 사용하여 이루어진다.

사실 이 구성 요소는 데이터 선택기(data selector)라는 것이 더 적절한 이름이다.

멀티플렉서는 제어선의 값에 따라 여러 개 입력 중에서 하나를 선택한다.

제어선은 주로 실행 중인 명령어에서 나오는 정보에 따라서 설정된다.

2. 어떤 유닛들은 명령어 종류에 따라 다르게 제어되어야 하는데 이 부분이 빠져있다.

데이터 메모리는 적재 명령어일때는 읽기, 저장 명령어일 때는 쓰기를 해야한다.

레지스터 파일은 적재 명령어나 산술/논리 연산 명령어일 때만 쓰기를 한다.

물론 ALU는 여러 가지 연산 중 하나를 수행해야 한다.

이 동작들도 멀티 플렉서처럼 명령어의 여러 필드 값에 따라 정해지는 제어선에 의해 통제된다.


그림 4.2 MIPS 부분집합의 기본적 구현. 필요한 멀티플렉서와 제어선을 포함하고 있다.

그림 4.2는 그림 4.1의 데이터패스에 주요 기능 유닛을 위한 제어선과 필요한 멀티플렉서 세 개를 추가한 그림이다.

제어 유닛(control unit)은 기능 유닛들과 두 멀티플렉서의 제어선 값을 결정하는 데 사용하는 것으로, 명령어를 입력으로 한다.

세 번째 멀티플렉서는 PC+4와 분기 목적지 주소 중 어느 것을 PC에 서야 할지 결정하는 것인데, ALU의 Zero 출력으로 제어된다.

이 출력은 beq 명령어에서 비교할 때에 사용된다.

MIPS 명령어 집합의 규칙성과 단순성은 간단한 디코딩 과정만으로 제어선의 값을 결정할 수 있게 하였다.

이 장의 나머지 부분에서는 이 그림의 세부 사항을 채워서 더 좋게 만들려고 한다.

그러려면 더 많은 기능 유닛을 추가하고 유닛 간의 연결을 늘려야 하며,

각 명령어 종류에 대해 어떤 행동을 취해야 할지 제어할 수 있도록 제어 유닛을 개선해야 한다.


4.2 논리 설계 관례

컴퓨터의 설계에 대하여 논의하기 위해서는

컴퓨터를 구현하고 있는 논리회로가 어떻게 동작하고 또 컴퓨터가 어떻게 클러킹되는지를 결정해야 한다.

MIPS 구현에 쓰이는 데이터패스 요소는 두 가지 종류의 논리 소자들로 구성된다.

: 데이터 값에만 동작하는 소자, 상태를 포함하는 소자

데이터 값에만 동작하는 소자는 모두 조합소자(combinational element)인데

- 조합소자 : AND 게이트나 ALU 같은 연산형 소자

그 의미는 그들의 출력이 현재의 입력에만 의존한다는 것이다.

조합소자는 같은 입력이 주어지면 항상 같은 출력을 낸다.

설계에 쓰이는 또 다른 종류의 소자들은 조합소자가 아니고 대신 상태(state)를 갖는다.

소자에 내부 기억장소가 있으면 상태를 갖게 된다.

이러한 소자들을 상태소자(state element)라고 부른다.

- 상태소자 : 레지스터나 메모리 같은 메모리 소자

상태소자는 적어도 2개의 입력과 1개의 출력을 갖는다.

꼭 있어야 되는 입력은 기록할 데이터와 클럭이다.

클럭 입력은 데이터 값이 소자에 기록되는 시점을 결정한다.

상태소자의 출력은 이전 클럭 사이클에 기록된 값이다.

논리적으로 가장 간단한 상태소자 중 하나는 D형 플리플롭인데

이 D형 플립플롭에는 두 개의 입력(데이터 값과 클럭)과 하나의 출력이 있다.

MIPS 구현에는 3가지 상태소자(플립플롭, 메모리, 레지스터)가 사용된다.

상태소자에 언제 쓸 것인가는 클럭이 결정하지만, 상태소자의 값을 읽는 것은 언제라도 가능하다.

상태를 포함하는 논리소자들은 순차회로(sequentail circuit)라 부르는데

이는 이들의 출력이 입력뿐만 아니라 내부 상태에도 의존하기 때문이다.


클러킹 방법론

클러킹 방법론(clocking methodology)은 신호를 언제 읽을 수 있고 언제 쓸 수 있는 지를 정의한다.

- 클러킹 방법론 : 데이터가 언제 유효한 값을 가지고 언제 안정되는지를 클럭 기준으로 결정하는 데 사용하는 방법.

읽기와 쓰기의 타이밍을 명시하는 것은 중요하다.

신호를 읽고 있는데 동시에 누군가가 새로운 값을 쓴다면,

읽은 값이 옛 값일 수도 있고 새로 쓴 값일 수도 있고 심지어는 두 값이 뒤섞인 것이 될 수도 있기 때문이다.

컴퓨터 설계는 이런 예측 불가능성을 용납하지 못한다.

클러킹 방법론은 예측 가능성을 보장하기 위해 고안되었다.

단순화를 위해 에지 구동 클러킹(edge-triggered clocking) 방법론을 가정한다.

- 에지 구동 클러킹 : 모든 상태 변화가 클럭 에지에서 일어나는 클러킹 방법

에지 구동 클러킹 방법론은 순차논리소자에 저장된 값은 클럭 에지에서만 바꿀 수 있다는 것을 의미한다.

클럭 에지란 그림 4.3에서 보듯이 낮은 값에서 높은 값 혹은 그 반대로의 빠른 변이를 말한다.

상태소자들만이 데이터 값을 저장할 수 있기 때문에 모든 조합회로는 상태소자에서 입력을 받고 상태소자로 출력을 내보낸다.

입력은 이전 클럭 사이클에서 쓴 값이고 출력은 다음 클럭 사이클에서 사용할 수 있는 값이다.


그림 4.3은 일단의 조합회로를 둘러싸고 있는 두 개의 상태소자를 보여 주고 있다.

이 회로는 하나의 클럭 사이클에 동작한다.

즉 모든 신호가 상태소자 1에서 나와서 조합회로를 거쳐 상태소자 2까지 전달되는 데 하나의 클럭 사이클이 걸린다.

신호들이 상태소자 2에 도착하는 데 필요한 시간이 클럭 사이클의 길이를 정의하게 된다.

그림 4.3 조합논리회로, 상태소자, 클럭은 밀접하게 연관되어 있다.

동기식 디지털 시스템에서는 상태소자가 내부 저장장치에 언제 값을 쓸 것인지를 클럭이 결정하게 된다.

상태소자의 모든 입력은 활성화된 클럭 에지가 상태를 바꾸기 전에 안정된 값에 도달해야 한다.

이 장의 모든 상태소자(메모리도 포함)는 상향 에지 구동이라고 가정한다.

즉 모든 상태소자는 상향 클럭 에지에서 값이 바뀐다.


매 클럭 에지마다 상태소자에 쓰기가 행해지는 경우는 앞으로 쓰기 제어신호(control signal)를 표시하지 않겠다.

- 제어신호 : 멀티플렉서의 입력을 선택하거나 기능 유닛의 연산을 지시하기 위해 사용되는 신호.

기능 유닛에 의해 연산되는 정보를 가지고 있는 데이터 신호에 대비된다.

반대로 상태소자가 매 클럭마다 갱신되는 것이 아니라면 쓰기 제어신호가 분명하게 표시되어야 한다.

클럭 신호와 쓰기 제어신호는 상태소자의 입력이며, 쓰기 제어신호가 인가되고 활성화 클럭 에지일 때만 상태소자가 변하게 된다.

'인가된(asserted)'이라는 용어는 논리적으로 높은 신호를 표시하며

'인가(assert)'라는 용어는 신호를 높은 값으로 만든다는 뜻이다.

논리적으로 낮은 값을 표시하기 위해서는 '비인가(deassert)'또는 '비인가된(deasserted)'이라는 용어를 사용한다.

인가 혹은 비인가라는 용어를 사용하는 이유는

하드웨어를 구현할 때 때때로 1이 논리적으로 높은 값을 나타내기도 하고 때때로 1이 논리적으로 낮은 값을 나타내기도 하기 때문이다.


그림 4.4에서 보는 바와 같이 에지 구동 방법론은

레지스터 내용을 읽고 그 값을 조합회로로 보내고 같은 레지스터에 쓰는 작업 모두가 한 클럭 사이클에 일어나는 것을 허용한다.

그림 4.4 에지 구동 방법론은 경쟁관계(race)를 발생시키지 않으면서

같은 클럭 사이클에 상태소자를 읽고 쓸 수 있게 해 준다.

경쟁관계가 발생하면 이상한 데이터 값이 된다.


32비트 MIPS가 취급하는 거의 모든 데이터가 32비트 폭을 갖기 때문에,

이 프로세서의 상태소자와 논리소자의 입력과 출력 폭은 거의 다 32비트이다.

그림에서 버스(bus)는 굵은 선으로 표시할 것이다.

버스는 폭이 2비트 이상인 신호들이다.

어떤 때는 여러 버스들을 합쳐서 더 넓은 버스를 만들기도 한다.

끝으로 데이터를 운반하는 신호와 구별하기 위해 제어신호는 파란색으로 나타낸다.