View
5. Computer Architecture - [밑바닥부터 만드는 컴퓨팅 시스템]
sm_amoled 2019. 11. 24. 13:25이 글은 insight 출판사의 [밑바닥부터 만드는 컴퓨팅 시스템 / The Elements of Computing System]이라는 책에 있는 프로젝트(과제)를 수행하는 글입니다.
해외에서는 nand2tetris라는 이름의 프로젝트로 알려져 있습니다! 동일한 내용으로 구성되어 있으니, nand2tetris를 공부할 때 참고바랍니다.
HW에 대한 내용을 소개한다. 앞서 배운 개념들과 함께 Hack 컴퓨터의 플랫폼을 구현해보자. ( 최적화따위는 개에게 던져주자. 작동방식에 대한 공부니깐 부담없이!)
배경
내장식 프로그램 Stored Program
컴퓨터의 유연성 (다양한 프로그램의 구동)은 내장식 프로그램 덕분에 가능하다. 프로그램은 HW에 내장되지 않고 데이터처럼 저장되고 연산된다. 여러 명령어가 합쳐져서 프로그램이 동작하게 된다.
폰노이만 구조
보편 튜링 기계_universal turing machine : 간단한 추상적 컴퓨터 모델. 시스템의 논리적 기초 분석에 이용된다.
폰 노이만 기계 _von neumann machine : 현대 컴퓨터 플랫폼의 실제 구조. CPU를 기반으로 메모리장치와 통신하고, 입력장치에서 데이터를 받고 출력장치로 데이터를 준다. 메모리는 조작할 데이터와 수행할 명령어까지 저장한다.
메모리
폰 노이만 기계의 메모리는 데이터와 명령어를 모두 저장한다. 보통 두 정보는 구분지어서 저장된다. 그러나 2진수 형태의 RAM 구조에 저장되는 것은 같다. 유일한 주소를 가지는 word에 저장되어 특정할 수 있다. (개별 선택이 가능하다)
데이터 메모리
변수, 배열, 객체등의 개념은 결국 2진 숫자열로 변환되어 데이터 메모리에 저장된다. 주소를 통해 개별적인 읽기, 쓰기가 가능하다.
명령어 메모리
고수준의 명령어는 여러 2진 명령어로 변환되어 명령어 메모리에 저장된다. CPU는 명령어 메모리에서 명령어 하나를 읽고, 해석하고, 수행하고, 다음 명령어를 찾는다. 보통 명령어 메모리에는 기계어로 번역된 1 word 짜리 명령어가 저장되는데, 2 word 이상의 명령어가 저장될 수도 있다.
중앙처리장치 CPU : Central Processing Unit
프로그램의 명령어를 실행하는 핵심적인 장치. 계산수행, 메모리 읽고 쓰기, 명령어 점프의 동작을 수행한다. 이를 위해 3가지 HW가 관여한다.
- 산술논리연산장치 ALU : 컴퓨터가 지원하는 모든 저수준의 산술,논리 연산을 수행한다.
- 레지스터 : CPU의 빠른 계산속도를 위해 존재한다. 메모리에 접근해 읽고 쓰는 시간이 매우 길기 때문에 (캐시메모리가 없다면 1만배 이상 차이난다고 보면 될거 같다) 레지스터에 잠시 저장한다.
- 제어장치 : 명령어 해석의 역할을 수행한다. ALU, 레지스터, 메모리가 실행할 명령을 전달하고, 다음 인출할 명령어와 실행할 명령어도 파악한다.
레지스터
CPU가 K라는 메모리주소에 있는 데이터를 필요로 한다면 아래의 과정을 거쳐야한다,
- RAM에게 CPU가 K를 전달
- 주소가 K인 메모리에 접근
- RAM[K]의 내용을 CPU에게 전달
이는 매우 느리고 비효율적인 방법. 비용도 많이 든다.
레지스터는 RAM과 기능은 동일하지만 읽고 쓰기 및 탐색의 비용이 매우 작다. CPU내부에 존재하기 때문에 물리적 거리도 매우 짧고, 개수가 적어 탐색이 쉽다.
-
데이터 레지스터 : CPU의 단기기억 메모리. CPU계산의 중간값을 임시로 저장할 때 사용한다.
-
주소 지정 레지스터 Addressing Register : CPU가 메모리접근을 위해 사용하는 레지스터. 명령어에 주소가 포함되지 않는 경우 사용한다. ( Hack 언어의 경우 명령어에 주소를 포함하기 어려우므로 메모리접근을 위해 거의 매번 주소지정 레지스터를 이용한다 )
-
프로그램 계수기 레지스터 Program Counter Register : CPU가 다음 실행할 명령어의 주소를 저장할 때 사용하는 레지스터. 프로그램 카운터의 값은 명령어 메모리에서 다음 인출할 명령어 주소를 가리킨다. 평소에는 1 Word씩 증가하나, goto문을 만나면 지정된 값으로 초기화한다. 앞으로 이를 PC라고 부르겠다.
입력과 출력
수많은 I/O장치를 컴퓨터와 통신할 수 있도록 각자 설정을 만들긴 비용이 많이 들게되므로, 컴퓨터는 수많은 장치들을 (아직 출시되지 않은 장치까지) 모두 똑같이 처리하는 기법이 필요하다.
메모리 매핑 I/O _memory mapping I/O : I/O장치와 컴퓨터가 연결되면 빈 메모리에 해당 장치가 사용할 공간을 할당해준다.
만약 입력장치에 변동이 있으면 입력장치가 RAM에 해당 내용을 기록하고, CPU는 RAM에서 해당 데이터를 받아와 반영한다. (마우스가 움직이면 RAM에 기록된 변동사항을 CPU가 처리)
출력할 내용이 있으면 RAM에 CPU가 기록을 하고, 출력장치는 RAM에서 해당 데이터를 받아와 구동한다. (스크린에 출력할 내용을 RAM에 기록하면 모니터가 해당 사항을 출력)
이를 통해 앞으로 연결할 I/O장치의 종류와 무관하게 전체 플랫폼의 설계가 가능하다. I/O장치를 활용할 때도 시작주소만 기록해두고 필요할 때 찾아서 접근(시작주소 + 0x32처럼 접근)하면 된다.
Hack HW 플랫폼 명세
여기에서부터는 메모리데이터를 RAM으로, 명령어데이터를 ROM으로 부르겠습니당.
개요
앞의 장과 절에서 설명한 Hack 컴퓨터의 정보에 대해 다시 기록해보자면 16Bit 폰 노이만 기계로 CPU, 명령어/데이터 메모리 모듈 각 1개, 스크린, KBD로 구성되어 있다. 외부수단을 통해 load한 프로그램을 명령어 메모리에서 읽어 실행한다.
CPU는 ALU, D, A, PC 레지스터로 구성된다. D는 데이터만 담고, A는 데이터, RAM/ROM 주소 등을 담는다. 핵의 기계어는 주소명령어 0--- ---- ---- ---- 또는 계산명령어 1xxa cccc ccdd djjj 로 구성된다. PC 레지스터의 출력은 ROM의 입력과 연결된다. PC값에 따라 ROM은 ROM[PC]를 계속 출력한다. 이는 현재 명령어에 해당한다.
전반적인 연산은 다음과 같다.
- 실행 execute : 현재 명령어가 여러 칩에 전달된다. 주소명령어라면 A 레지스터에 값이 전달되고, 계산 명령어라면 ALU와 레지스터가 명령을 수행한다.
- 인출 fetch : ALU의 출력과 jump bit을 비교해 조건이 틀리면 PC++, 조건이 맞으면 PC = A 를 수행한다. 다음 CLK때는 PC가 가리키는 명령어가 ROM의 출력이 된다.
- 1사이클이 1CLK에 수행되며, 실행 - 인출 - 실행 - 인출 을 반복한다.
이제부터 설계할 칩들은 모두 앞 장에서 설계했던 칩들을 기반으로 만들 수 있는 것들이다. CPU는 ALU를 기반으로 16Bit 레지스터로 만든 레지스터와 16Bit 계수기로 만든 PC가 들어간다. ROM/RAM 역시 메모리 장치들이다. I/O 디바이스들 역시 RAM과 동일한 인터페이스의 내장 칩으로 구현한다.
중앙처리장치 CPU
CPU는 명령어 인출에 필요한 ROM과 데이터를 읽고 쓰는 RAM에 따로 연결되어 있다.
WriteM이 1이면 AddressM에 M의 값이 저장될 주소를, OutM에 M의 값을 반환한다. reset이 1이면 다음 주소 대신 명령어주소에 0을 전달한다.
명령어 메모리 ROM
직접접근 읽기전용 메모리_direct access read only memory 또는 ROM 칩 상에 구현된다. 명령어 주소를 전달하면 해당 명령어를 반환한다.
데이터메모리 RAM
Hack의 데이터메모리의 인터페이스는 RAM과 같다.
address에 주소를 넣으면 out으로 데이터가 나온다. (조합연산) in에 값 V를 넣고 load Bit을 1로 set하면 해당 주소에 V가 저장된다. (순차연산)
데이터메모리는 기본적인 범용 데이터 저장공간 + 메모리 맵을 통한 I/O 장치와의 통신도 담당한다.
메모리 맵
매모리맵은 각각의 I/O장치마다의 나름의 규약에 따라 통신한다. HW의 인터페이스와 I/O장치가 통신하는 내장 칩을 정의하고, 전체 메모리 모듈을 만들자. Hack의 경우 스크린과 키보드를 I/O장치로 이용한다.
스크린
Hack의 스크린은 512X256의 흑백 픽셀로 구성되어있다. 메모리맵을 통해 통신하며, Screen이라는 칩을 통해 메모리맵이 구현된다. 칩에 읽고 쓰기가 가능하며, 칩에 기록한 Bit은 픽셀로 표시된다.
Screen의 기능은 16Bit 8K RAM과 동일하다. 좌상단부터 한 행씩 채워지는 형태로 메모리가 배정되어있다.
키보드
키보드는 일반적인 키보드와 동일한 표준형이다.
메모리맵으로 통신하며, Keyboard라는 칩을 통해 메모리맵에 구현된다.
눌린 Key의 ASCII CODE값을 반환한다. 일부 특수키의 입력 또한 반환한다.
전체 메모리
Hack의 전체 주소 공간은 메모리라는 칩으로 제공된다. RAM과 스크린 맵, 키보드 맵이 포함된다.
0x4000-0x5FFF는 스크린 메모리맵이다.
0x6000은 키보드 메모리맵이다.
0x6001~은 접근 불가능하다.
컴퓨터 Computer
Hack 시스템의 최상위 칩. CPU, RAM, ROM, 스크린, 키보드 + etc로 구성된다. 프로그램의 실행을 위해 ROM에 미리 Load 해야한다.
reset이 0이면 프로그램을 실행한다. reset이 1이면 프로그램을 초기화한다
구현
중앙처리장치 CPU
대부분의 동작이 CPU에서 이루어지므로 CPU설계가 가장 중요하다. CPU가 다음 실행할 명령어를 fetch해서 실행시키는 논리게이트 구조를 만드는 것이 목표이다!
위 그림에는 데이터나 주소의 경로만 담아져있고, CPU의 제어논리가 빠져있는 불완전한 CPU이다. 명령어의 해석, 실행, 다음 명령어 fetch의 작업을 수행하는 제어논리를 포함해야 한다
명령어 해석 Instruction Decoding
들어온 명령어가 A 명령어인지 C 명령어인지 알아내기 위해 16Bit을 쪼개야한다.
[ 명령어의 form : ixxa cccc ccdd djjj ]
i bit은 해당 명령어가 A 명령어(i=0)인지 C 명령어(i=1)인지를 구분한다. A 명령어인 경우 뒤 15 Bit을 주소로 이해하고, C 명령어인 경우 뒤의 Bit들을 comp, dest, jump Bit으로 이해한다.
명령어 실행 Instruction Execution
명령어의 필드를 여러 칩들에게 동시에 전달해서 실행에 필요한 작업을 알리는 역할을 한다. C 명령어일 때, a Bit은 A 레지스터와 M 메모리 중 어느걸 이용할 지 알린다. c Bit은 ALU가 계산할 함수를 정하고, d Bit은 계산결과를 저장할 위치를 고른다.
다음 명령어 인출 next instruction fetch
CPU의 부품인 PC는 다음 명령어의 주소를 정하고 출력한다. 대부분의 경우 프로그램은 다음 명령어를 인출한다. PC(t)=PC(t-1)+1
goto 연산(분기문)의 경우 A 레지스터에 이동할 주소를 저장한 뒤 jump 명령어를 사용하면 된다.
If jump(t) then PC(t)=A(t-1) else PC(t)=PC(t-1)+1
이 기능은 jump의 조건을 판단하는 j Bit과 ALU의 출력신호에 따라 PC의 load Bit을 set해주면 된다. 프로그램을 종료하려면 reset Bit을 set하여 PC의 값을 0으로 만들면 된다.
메모리 칩
Hack의 메모리는 RAM16K, 스크린, 키보드의 세가지 low level칩을 합친 것이다. 메모리의 사용자에게는 동일한 메모리처럼 보이기 위해 연속된 단일 메모리처럼 제공된다.
RAM16K 0x0000 to 0x4000 + 스크린 0x4001 to 0x5FFF + 키보드 0x6000
컴퓨터칩
CPU와 메모리칩을 구현하고나면 전체 컴퓨터칩은 단순하게 설계된다.
정리
Hack 컴퓨터는 정량적인 면에서는 사양이 일반 컴퓨터보다는 많이 떨어지지만, 개념적으로는 폰 노이만 구조를 따르는 대부분의 컴퓨터와 동일하다. 컴퓨터 시스템은 기능적으로 두 종류로 나뉜다.
- 범용 컴퓨터 general perpose computer : 여러 프로그램을 바꿔가며 쉽게 실행
- 전용 컴퓨터 dedicated computer : 시스템에 내장된 컴퓨터
전용컴퓨터의 ROM에는 특별한 프로그램이 장착되고, 이게 실행가능한 유일한 프로그램이라는 점을 제외하고는 범용과 전용은 동일한 개념을 공유한다.
일반적인 컴퓨터는 RAM/ROM을 구분하지 않는다. 구조상 명령어의 주소와 데이터의 주소에 동시접근이 불가능하므로 두 명령의 주기를 따로 두고 실행한다.
- 인출 주기 fetch cycle : 명령어 주소를 메모리에 전달. 명령어 레지스터에 저장된 현재 명령어 즉시 출력
- 실행 주기 execute cycle : 명령어 해석. 데이터의 주소가 있으면 메모리에 전달해 값을 반환받는다.
But, Hack에서는 간단히 설계하여 한 주기 안에 명령어와 데이터 접근이 가능하지만, 동적으로 자유로운 프로그램을 만들기는 힘들다.
Hack의 I/O 또한 매우 단순하다. Hack의 스크린은 작고 흑백만 지원하지만, 일반 컴퓨터의 경우 크고 컬러와 밝기까지 지원한다. 또한 현대 컴퓨터는 픽셀 to 메모리 방식이 아닌, CPU가 그래픽카드에 고수준의 그래픽명령어를 전송한다. CPU대신 그래픽카드가 그래픽과 관련된 업무를 능숙하게 처리해준다.
컴퓨터의 HW 성능 향상을 위해 계층메모리(캐시), IO접근방식개선, 파이프라인, 병렬화, 명령어 예비인출 등의 최적화기법을 이용한다.
프로세서의 성능개선을 위한 두가지 분파가 존재한다
- CISC Complex Instruction Set Computer : 더 정교한 명령어를 통해 고성능을 꾀한다!
- RISC Reduced Instruction Set Cimputer : 더 단순한 명령어를 통해 HW의 처리속도 향상을 꾀한다!
아, 물론 우리의 hack은 아직 두 분파와 관계가 없을 정도로 간단하다.
프로젝트
CPU구현에 제어논리를 추가하여 완전한 CPU를 만들어보자!
'학부생 CS > Elements of Comp-Sys' 카테고리의 다른 글
6-2. Assembler - [밑바닥부터 만드는 컴퓨팅 시스템] (0) | 2019.11.27 |
---|---|
6-1. Assembler - [밑바닥부터 만드는 컴퓨팅 시스템] (0) | 2019.11.27 |
4. Machine Language - [밑바닥부터 만드는 컴퓨팅 시스템] (0) | 2019.11.23 |
3. Sequential Logic - [밑바닥부터 만드는 컴퓨팅 시스템] (0) | 2019.11.23 |
2. Boolean Arithmetic - [밑바닥부터 만드는 컴퓨팅 시스템] (0) | 2019.11.23 |