Published on

실제 컴퓨터의 구조

Authors
  • avatar
    Name
    유사공대생
    Twitter

기본 내용들을 모두 숙지했다면, 지금부터 조립하여 실제 컴퓨터를 만들 것이다. 여러 부분이 함께 작동하려면 일종의 '접착제'에 해당하는 요소가 필요하다.

명령어 레지스터

컴퓨터가 한 프로그램을 한 번에 한 명령어씩 실행한다고 착각할 수도 있다. 하지만 컴퓨터 내부에서는 더 많은 일이 벌어진다. 명령어를 실행하려면 어떤 일이 벌어져야 하는가?

image

컴퓨터에서 벌어지는 일을 위 그림처럼 두 단계로 이루어진 상태 기계(state machine) 으로 설명할 수 있다.

처음에 컴퓨터가 해야할 일은 메모리에서 명령어를 가져오는 패치(fetch)다. 일단 명령어를 가져오고 나면 이 명령어를 어떻게 실행할 지 고민해야 한다.

명령어를 실행하려면 메모리에 접근해야 할 경우가 많다. 이 말은 다른 목적으로 메모리를 사용할 때 패치한 명령어에 편하게 접근할 수 있도록 저장할 다른 위치가 필요하다는 뜻이다.

image

위 그림에서는 CPU에 명령어 레지스터(instruction register)를 추가해서 현재 실행 중인 명령어를 저장한다.

데이터 경로와 제어 신호

image

프로그램 카운터의 값을 메모리 주소 버스에 넣을 방법과 메모리에 있는 데이터를 명령어 레지스터로 넣을 방법이 필요하다. 이런 고민을 계속해서, 여러 명령어 집합을 구현하는 데 필요한 모든 연결을 결정해야 한다. 결과적으로 위와 같은 연결이 생긴다. 이 그림을 보면 복잡해 보이겠지만, 실제로는 앞에서 우리가 살펴봤던 내용인 레지스터, 실렉터, ALU, 트라이 스테이트 버퍼 등일 뿐이다.

이 그림은 꽤 복잡해 보이지만 단지 개념도일 뿐이다. 실제 컴퓨터보다 이 다이어그램은 훨씬 더 간단하다. 주소 실렉터는 단지 3방향 교차로일 뿐이고, 데이터 실렉터는 4방향 교차로다. 데이터 버스나 주소 버스의 한쪽에는 6장에서 설명할 I/O 장치 등이 연결된다.

여기서 새로운 부분은 간접 주소 레지스터(indirect address register) 뿐이다. 이 레지스터가 필요한 이유는 간접 주소 지정을 사용할 때 메모리에서 읽어온 주소를 어딘가에 저장해야 하기 때문이다. 이건 명령어 레지스터에 메모리에서 읽어온 명령어를 저장하는 것과 비슷하다.

단순화를 위해 위 그림에서는 모든 레지스터에 전달되는 시스템 클록을 생략했다. 간단한 레지스터와 마찬가지로 이 그림에 있는 레지스터에도 다음 클록 틱에 데이터가 저장된다고 가정하자. 마찬가지로 프로그램 카운터와 메모리도 제어 신호가 지시하는 동작을 클록이 틱에 맞춰 수행한다. 실렉터 등의 다른 모든 구성요소는 순전히 조합 논리이기 때문에 클록이 필요하지 않다.

데이터 흐름 제어

입력과 출력에 대해 모두 알았으므로 이제 교통을 제어하는 장치를 만들 때다. 이 장치가 어떻게 작동해야 할지는 다음 예제를 보면서 생각해보자.

어떤 명령어든 처리하려면 페치를 해야 한다. 페치를 하려면 다음과 같은 신호가 필요하다.

  • address source는 프로그램 카운터를 선택해야 한다.
  • 메모리를 동작시켜야 한다.(enable을 1로 함)그리고 r/w 는 읽기(1)로 설정해야 한다.
  • 명령어 레지스터를 동작시켜야 한다.(enable을 1로 함)

주의

(이 예제의 RAM은 클록을 사용하지 않는 램이라는 점에 유의하라 - 요즘은 대부분 동기화된 램을 사용하므로 클록 없이는 램이 작동하지 않는다. 비동기 램을 사용하고 본문에서 설명한 대로 신호가 공급되는 경우 실제 시스템에서 발생하는 일을 생각해보자.

address source가 프로그램 카운터를 선택했으므로 프로그램 카운터에 있는 값이 주소 버스에 들어간다. 약간의 시간이 지나면 주소 버스에 들어 있는 주소에 해당하는 메모리에 저장된 값이 데이터 버스에 전달되고, 이 값은 데이터 버스에 연결된 장치 중 활성화된-enable이 1 명령어 레지스터의 입력에 연결된다.

이제 클록 틱이 발생하면 명령어 레지스터는 입력받은 값을 저장한다. 한편 이 과정에서 시스템의 나머지 부분은 아무 일도 하지 못하도록 enable을 0으로 설정해야 한다는 점에 유의하라)


예제

다음 예제로는 누산기의 값을 명령어의 주소 부분이 가리키는 메모리에 있는 값에 해당하는 주소(따라서 간접 주소 지정)에 저장하는 경우를 생각해보자. 페치는 앞에서 설명한 방식대로 수행할 수 있다.

간접적으로 주소를 메모리에서 가져오기 위해 다음과 같이 신호를 설정해야 한다.

  • address source를 명령어 레지스터로 지정한다. 이 경우 명령어 레지스터의 주소 부분이 주소 버스에 연결된다.
  • 메모리를 동작시켜야 한다.(enable을 1로 함) 그리고 r/w는 읽기(1)로 설정해야 한다.
  • 간접 주소 레지스터를 동작시켜야 한다.(enable을 1로 함)

클록 틱이 지나면 간접 주소 레지스터에 명령어의 주소 부분이 가리키던 주소에 있던 값이 들어간다. 이제 누산기에 있는 값을 이 주소에 저장해야 한다.

  • address source를 간접 주소 레지스터로 설정해야 한다.
  • data bus enable을 1로 설정해야 한다.
  • 메모리를 동작시켜야 한다.(enable을 1로 함). 그리고 r/w는 쓰기(0)으로 설정해야 한다.
  • 프로그램 카운터를 증가시킨다.(ld/cnt를 0으로)

image

페치와 실행에 여러 단계가 필요하므로 각 단계를 추적할 카운터가 필요하다. 이 카운터의 내용과 명령어의 명령코드와 모드 부분이 제어 신호를 결정한다. 가장 복잡한 연산의 경우 3단계가 필요하기 때문에 카운터는 2비트 카운터여야 한다. 위 그림에서 볼 수 있다.

그림의 큰 박스는 랜덤 논리(random logic) 라는 것으로 가득 차 있다. 지금까지 살펴본 논리 다이어그램은 일반적인 패턴을 따른다. 실렉터나 레지스터 등의 기능 블록은 더 간단한 블록을 정해진 패턴으로 조합해 만들어진다. 여기서 구현하려는 교통 제어 장치처럼 복잡한 구조를 구현하는 경우, 정해진 개수의 입력이 있고 이 입력들을 정해진 개수의 출력에 연관시켜야 하는데 출력에 어떤 규칙성이 없을 때가 있다. 이런 경우(게이트를 연결해 만든) 회로도가 마치 쥐 둥지가 얽히고설킨 것 처럼 보인다. 여기서 '랜덤'이라는 말이 나왔다.

image

하지만 또 다른 방법으로 교통 제어 장치를 구현할 수도 있다. 랜덤 논리 대신 적당한 크기의 메모리를 사용할 수도 있다. 위 그림처럼 카운터의 출력과 명령어의 명령코드와 주소 지정 모드 부분을 메모리 주소에 연결한다.

image

각각의 19비트 메모리 워드는 위 그림처럼 구성된다.

이런 방법은 좀 이상해 보일 수도 있다. 반면 이 또한 랜덤 논리 대신 메모리를 사용해 구현한 또 다른 상태 기계일 뿐이다. 한편 이 자체로도 작은 컴퓨터 같아 보인다. 이 두 가지 해석은 모두 옳다. 컴퓨터는 상태 기계이기 떄문에 이 회로도 상태 기계다. 프로그래밍이 가능하기 때문에 이 회로도 컴퓨터다.

이런 식으로 구현하는 방법을 마이크로코드를 썼다. 라고 한다. 이때 메모리 내의 내용이 마이크로 코드(microcode) 다. 그렇다. 우리는 큰 컴퓨터를 구현하기 위해 작은 컴퓨터를 사용 중이다.

마이크로 명령어 들여다보기

image

이제 우리가 설명한 예제를 보여주는 마이크로명령어(microinstruction) 부분을 살펴보자. 위 그림을 보자.

마이크로코드 메모리로 ROM을 쓰면 좋다. ROM을 쓰지 않으려면 어딘가에 마이크로코드를 저장했다가 필요할 때 마이크로코드를 불러오는 회로가 필요하다. 하지만 상황에 따라 RAM을 사용하거나 ROM과 RAM을 섞어서 사용하는 것을 정당화할 수도 있다. 일부 인텔 CPU는 버그를 수정하기 위해 패치(patch- 코드의 일부 또는 전부를 덮어씀)할 수 있는 쓰기 가증한 마이크로코드를 포함한다. HP-2100같은 일부 컴퓨터에는 쓰기 가능한 제어 저장소(writable control store)가 있다. 이 저장소는 명령어 집합을 확장하기 위해 쓸 수 있는 마이크로코드를 저장하는 RAM이다.

오늘날 쓸 수 있는 마이크로코드를 변경할 수 있도록 허용하는 경우는 드물다.

그 이유는

  1. 생산자는 사용자가 만든 마이크로코드를 사용한 명령어로 프로그램을 작성하도록 허용하는 것을 원치 않는다. 일단 이런 명령어에 의존성이 생기고 나면 생산자가 하드웨어를 변경하기 어려워지기 때문이다.
  2. 마이크로코드에 버그가 있으면 컴퓨터에 해를 입힐 수도 있다. 예를 들어, 우리 CPU에서 메모리를 활성화하면서 동시에 데이터 버스를 활성화하면 토템-폴 출력이 서로 연결되면서 내부 트랜지스터가 타버린다.