이 글은 Crash Course의 Computer Science를 보고 정리한 글입니다.
컴퓨터에서 중앙 처리 장치(Central Processing Unit; CPU)는 인간의 심장과 같다.
CPU의 일은 프로그램을 실행하는 것이다. 프로그램은 instruction(명령어)라고 하는 개별적인 동작의 연속으로 구성되어 있다. 컴퓨터가 무엇을 해야 하는지 instruct(명령)하는 것이기 때문에, instruction(명령어)하고 부른다.
더하기(add)나 빼기(subtract)와 같은 수학 명령어라면, CPU는 ALU가 수학 연산을 하도록 설정할 것이다. 메모리 관련 명령어라면, CPU는 메모리에 read와 write동작을 하도록 설정할 것이다.
마이크로아키텍처(microarchitecture)라고 하는 상위 수준의 개념으로 접근해보자. 우선 메모리가 필요하다. 간단하게 16개의 저장공간이 있고, 각 저장공간에는 8bit를 저장할 수 있는 RAM이 있다고 가정하자. 그리고 프로세서는 A, B, C, D라고 하는 4개의 8bit 메모리 register를 갖고 있다고 가정하자. 이 레지스터들은 값들을 조작하고 임시로 저장하는 데 사용할 것이다. 알다시피 data는 메모리에 이진수 형태로 저장된다. 프로그램도 역시 메모리에 저장된다.
CPU가 지원하는 각 명령어(instruction)에는 operation code(OPCODE)가 부여되어 있는데, 우리의 CPU는 다음과 같이 부여되었다고 가정하자.
그러면 메모리에 저장되는 8bit 중 앞에 4bit는 OPCODE를 나타내고 뒤에 4bit는 연산에 사용될 data가 어디서 오는가를 나타낸다. 이것은 레지스터일 수도 있고, 메모리의 주소일 수도 있다.
CPU 동작을 완성하기 위해서 2개의 레지스터가 더 필요하다.
첫 번째로는 프로그램이 어디에 있는지 추적할 수 있는 레지스터가 필요하다. 이것을 instruction address(명령어 주소) 레지스터라고 하고, 이름에서 알 수 있듯이 현재 instruction의 메모리 주소를 저장한다.
두 번째는 현재 수행되는 명령어가 저장되는 레지스터가 필요하다. 이 레지스터는 instruction(명령어) 레지스터라고 한다.
이제 간단한 컴퓨터 프로그램이 RAM에 다음과 같이 저장되어 있다고 가정하고 실행해보자.
처음 컴퓨터가 부팅되면, 모든 레지스터는 0에서 시작된다. CPU 동작의 첫 번째 단계는 fetch phase(인출 단계)라고 한다. instruction을 가져오는 것이다. 우선 RAM 모듈에 instruction address 레지스터를 연결한다. 레지스터의 값이 0이기 때문에 RAM은 0번지에 저장되어 있는 00101110이라는 값을 보내주고, instruction 레지스터에 00101110이 복사된다.
이제 instruction 하나를 메모리로부터 fetch 했으니 instruction을 실행하기 위해서 이 instruction이 무엇인지 알아내야 한다. 이 단계를 decode phase(해독 단계)라고 한다. 이 경우에 opcode인 첫 4bit는 0010이다. 이 opcode는 RAM에 저장된 값을 Regitster A로 옮겨 오는 "LOAD_A"라는 instruction을 나타낸다. RAM의 주소는 instruction의 뒤 4bit인 1110, 십진수로 14이다.
Control Unit은 instruction을 번역(decode)하고 해석한다. 다른 것과 마찬가지로, 이것 또한 논리 게이트로 구성된다. 예를 들어, LOAD_A 명령어를 해독하기 위해서는 opcode가 0010인지 체크하는 회로가 필요하다. 이것은 논리 게이트 몇 개로 만들 수가 있다.
이제 무슨 instruction을 처리해야 하는지 알았으니, 이 instruction을 실행하는 단계로 갈 수 있다. 이게 execute phase(실행 단계)의 시작이다. LOAD_A 검사 회로의 출력으로 RAM의 read enable을 켤 수가 있다. 그리고 주소 14를 RAM에 전송한다. 그럼 RAM에서 14번 주소의 값을 가져온다. 14번 주소의 값은 0000 0011(십진수 3)이다. LOAD_A instruction이기 때문에 이 값은 오직 Register A에 저장되어야 한다. RAM의 data를 4개(A, B, C, D) 레지스터에 전부 연결했더라도, LOAD_A 검사 회로는 Register A의 write enabel만 활성화시킨다. 그래서 RAM의 14번 주소의 값이 성공적으로 Register A로 load 될 수가 있다.
하나의 instruction이 완성됐으므로 모든 연결선을 끄고, 메모리에서 다음 instruction을 fetch 할 수 있도록 준비한다. 이를 위해, instruction address 레지스터를 1 증가시키고, execute phase를 종료한다.
LOAD_A는 우리의 CPU가 수행할 수 있는 여러 instruction 중에 하나이다. 다른 instruction은 다른 논리 회로(검사 회로)를 통해 decode 되고 해당 동작을 수행할 수 있도록 CPU에 구성되어 있다. 각각의 decode회로를 살펴보는 것은 너무 상세하기 때문에 Control Unit으로 통칭하여 단순화하겠다.
Control Unit은 마치 오케스트라의 지휘자와 같이 CPU의 다른 모든 파트를 지휘한다. 인출(fetch)/해독(decode)/실행(execute)의 전체 사이클이 한 번 끝났으니, 이 모든 것을 다시 시작할 준비가 되었다. 이제 fetch phase부터 다시 시작하자. 이전 사이클에서 execute phase가 종료되기 전에 instruction address 레지스터를 1 증가시켰으므로, instruction address 레지스터는 1을 갖고 있고, RAM은 주소 1번지에 저장된 값, 0001 1111을 instruction 레지스터에 보낸다. decode phase에서 opcode 0001은 LOAD_B instruction이고, 이것은 RAM에서 Register B로 값을 복사시키는 것이다. 이번에 메모리 위치는 1111로 십진수 15번이다. 이제 excute phase이다. Control Unit은 RAM의 15번지를 read 할 수 있도록 설정하고, Register B는 data를 받을 수 있도록 설정한다. 그리고 RAM에서 15번 주소의 값, 0000 1110(십진수 14)은 Register B에 저장된다. 마지막으로 instruction address 레지스터를 1 증가시키고, 또 하나의 사이클을 완료하게 된다.
다시 fetch부터 해보자. instruction address 레지스터 값이 2이므로 1000 0100을 instruction 레지스터에 가져오고 opcode 1000은 ADD instruction이다. 이 instruction은 4bit RAM 주소 대신 2bit짜리 2개 세트를 사용한다. 2bit는 4개의 값을 표현할 수 있으니, 우리 4개의 레지스터 중에 하나를 선택할 수 있다. 첫 번째 세트는 01이고, Register B를 나타낸다. 다음은 00으로 Register A를 나타낸다. 따라서, "1000 01 00"은 Register B의 값을 Register A의 값에 더하라는 instruction이다.
Control Unit은 올바른 레지스터를 선택해서 ALU에 입력해 주고 올바른 연산이 수행되도록 ALU를 설정한다. 이 ADD instruction을 위해서 Control Unit은 Register B를 enable 하고 저장된 값을 ALU의 첫 번째 입력으로 보낸다. 또한 Register A를 활성화하여 ALU의 두 번째 입력으로 보낸다. 그리고 Control Unit은 ADD opcode를 전달해서 ADD 연산이 수행되도록 ALU의 operation code를 설정한다. 마지막으로 연산 결과가 Register A에 저장되어야 한다. 하지만 바로 저장될 수는 없다. 이 결과가 ALU로 되돌아와서 다시 더해질 수 있기 때문이다. 그래서 Control Unit은 내부 레지스터에 연산 결과를 임시로 저장하고 ALU를 끈 다음, 목적지 Register에 값을 저장한다. 이 경우에 입력은 3과 14이므로 합은 17, 이진수로 0001 0001이다. 이 값은 현재 Register A에 있다. 이전과 마찬가지로 마지막 할 일은 instruction address 레지스터를 1 증가시키는 것이다. 이렇게 또 하나의 cycle이 완성되었다.
자, 이제 마지막 instructiion 0100 1101을 fetch 하자. 해독해보면, 0100은 STORE_A instruction이고 RAM 주소는 13이다. 마찬가지로 RAM 모듈에 address를 전달하지만, read enable 대신에 write enable을 한다. 같은 시간에 Register A도 read enable 하여 data 선에 Register A에 저장된 값이 통과하게 된다.
이렇게 우리의 첫 컴퓨터 프로그램을 실행됐다. 이 프로그램은 메모리로부터 2개의 값을 옮겨와서, 서로 합친 후에 결과를 메모리로 다시 저장하는 프로그램이었다.
물론 이것은 fetch, decode, execute phase의 각 단계를 설명하면서 CPU를 수동으로 전환하고 있었다. 하지만, 실제 모든 컴퓨터 속에는 CPU를 순서대로 작동시킬 수 있게 clock이라고 하는 부품이 존재한다. 이름에서 알 수 있듯이, clock은 정확하고 규칙적인 시간에 전기 신호를 발생한다. 이 신호는 Control Unit이 CPU의 내부 동작을 완벽하게 발맞춰 진행시킬 수 있게 해 준다. 물론 무작정 빨리 작동시킬 수는 없다. 아무리 전자라도 전선을 통과해서 신호가 안정될 때까지 시간이 필요하다.
CPU가 fetch-decode-execute 사이클의 각 단계를 수행하는 속도를 Clock speed라고 한다. 이 speed는 주파수 단위인 헤르츠(Hertz; Hz)로 표시한다. 2Hz는 1초에 2사이클이라는 의미이다.
최초의 단일칩 CPU는 1971년에 출시된 Intel 4004라는 4 bit CPU이다.
이 CPU는 최초의 프로세서임에도 불구하고, 740kHz로 작동했다. 1초에 74만 사이클이 수행된다는 것이다. 빠르다고 생각할 수도 있지만, 요즘 우리가 사용하는 프로세서와 비교하면 아무것도 아니다. 1메가 헤르츠(MHz)는 1초에 백만 clock 사이클이고, 우리가 사용하는 컴퓨터나 스마트폰은 몇 기가헤르츠(GHz)로 작동한다. 매 1초마다 수십억 개의 CPU 사이클이 작동한다는 뜻이다.
컴퓨터를 overclocking 해서 사용한다고 들은 적이 있을 것이다. clock 속도를 올리면, CPU의 속도를 올릴 수 있다. 보통 칩 제조사는 약간의 overclocking이 가능하도록 CPU를 설계한다. 하지만, 너무 많이 하면 CPU가 과열되거나 신호가 안정되는 속도보다 clock이 빨라질 수 있다.
underclocking에 대해서 많이 들어보진 못했을 것 같지만, 이것도 매우 유용하다. 때때로 프로세서가 최고 속도로 작동할 필요가 없을 때가 있다. 사용자가 자리를 떠났거나, 별다른 프로그램을 실행하지 않는 경우 CPU 속도를 느리게 해서, 전력 소비를 많이 줄일 수가 있다. 이것은 배터리로 동작하는 노트북이나 스마트폰에서는 아주 중요한 일이다.
이런 요구사항을 만족하기 위해, 요즘 많은 프로세서들은 상활에 맞게 clock speed를 높이거나 낮출 수가 있다. 이것을 dynamic frequency scaling(동적 주파수 스케일링)이라고 한다.
clock까지가 CPU의 부품으로 RAM은 CPU 바깥에 별도 부품으로 위치한다. 두 부품은 서로 address, data, enable 선들을 통해서 통신한다.
'컴퓨터공학 > 기초' 카테고리의 다른 글
고급 CPU 설계 (0) | 2022.08.02 |
---|---|
명령어와 프로그램 (0) | 2022.07.31 |
레지스터와 RAM (0) | 2022.07.30 |
컴퓨터는 어떻게 계산할까?-ALU편 (0) | 2022.07.28 |
이진수로 숫자와 문자 나타내기 (0) | 2022.07.28 |
댓글