컴퓨터 구조 수업의 목표는 MIPS CPU를 직접 디자인하는 것이다.
CPU를 디자인하기 전에, 먼저 MIPS CPU가 이해하고 사용할 수 있는 명령어에 대해 정리하자.
Instruction (명령어)
Instruction
컴퓨터가 사용하는 단어를 가리킨다.
만약 외국인과 대화를 하고 싶다면, 나는 그 외국인의 언어를 사용할 줄 알아야한다.
마찬가지로, 우리가 컴퓨터와 대화하기 위해서는 컴퓨터의 언어를 사용할 줄 알아야 한다.
instruction은 컴퓨터와 대화할 때 사용하는 단어 하나를 가리킨다.
Instruction Set
컴퓨터가 사용하는 어휘 (단어들의 집합) 을 가리킨다.
정확하게는 CPU가 이해하는 단어의 집합을 가리킨다.
따라서 CPU가 달라지면 컴퓨터가 이해하는 언어가 달라진다.
CISC vs RISC
사람의 언어도 언어마다 문법과 특징이 다르듯, 컴퓨터가 사용하는 어휘 체계도 각각 특징이 있다.
컴퓨터의 어휘 체계 (Instruction Set) 은 특징에 따라 크게 2가지로 구분이 가능하다.
CISC (Complex Instruction Set Computer)
아주 복잡한 어휘 체계를 가진 경우이다.
명령어의 길이가 제각각이고, 각각의 명령어도 다양한 기능을 수행한다.
x86, Motorola 68k 등의 CPU가 CISC 분류의 복잡한 어휘 체계를 사용한다.
RISC (Reduced Instruction Set Computer)
단순한 어휘 체계를 가진 경우이다.
명령어의 길이가 모두 동일하게 고정되어 있고, 각각의 명령어도 한가지 기능만 수행한다.
CPU를 단순하게 만들기 위해 명령어도 단순하게 만들었다.
MIPS, ARM 등이 RISC로 분류된다.
MIPS
이제 MIPS 라는 CPU의 특징을 정리해보자.
MIPS는 다양한 임베디드 시스템에서 사용되고 있다.
MIPS는 명령어/데이터의 크기에 따라 32-bit / 64-bit 버전 2가지가 존재한다.
(이번 학기에는 32bit 버전으로 학습한다.)
MIPS (RISC) 디자인 철학
1. 단순하게 만들려면 규칙적으로 만들어라 (Simplicity favors regularity)
MIPS는 모든 명령어의 길이가 동일하며, 명령어의 format도 종류가 적다.
때문에 CPU가 명령어를 해석할 때 단순한 과정으로 해석할 수 있다.
2. 작을수록 빠르다 (Smaller is faster)
MIPS의 어휘체계는 크기가 작다. (즉, 명령어의 수가 적다.)
CISC에서 명령어 1개로 수행할 수 있는 복잡한 기능은 RISC의 여러 명령어의 조합으로 실행할 수 있다.
따라서 명령어의 수가 적어도 기능적으로 부족한 점은 없다.
3. 자주 쓰이는 부분을 빠르게 만들어라 (Make the common case fast)
4. 어느 정도의 타협은 필요하다 (Good Design demands good compromises)
작을수록 빠르다고 해서 너무 작게 만들면 오히려 불편함을 야기할 수 있다.
위의 원칙을 준수하고자 하되, 어느정도 필요한 부분은 타협을 하는 융통성을 가지자는 내용이다.
Stored Program Concept
MIPS를 포함한 현대의 대부분의 컴퓨터는 모두 Store Program Concept에 따라 설계되었다.
이 구조의 핵심은 "실행하려는 모든 명령어, 데이터는 메모리에 저장되어 있다" 는 것이다.
컴퓨터는 기계이므로 0과 1만을 이해한다.
따라서 모든 명령어와 데이터는 0과 1의 조합으로 구성되며, 이 형태 그대로 메모리에 저장된다.
CPU는 메모리로부터 명령어와 데이터를 가져와 실행하고, 그 결과를 다시 메모리에 쓰는 행위를 반복한다.
(이때 메모리는 CPU와 떨어져 있기 때문에, Off-Chip 메모리라고 부르기도 한다.)
프로그램을 실행한다는 말은
사람이 작성한 프로그램을 컴퓨터가 이해할 수 있도록 기계어로 변환한 뒤 (컴파일)
프로그램을 실행할 때는 기계어로 구성된 프로그램을 메모리에 올리고 (로딩),
CPU가 프로그램의 명령어를 하나씩 가져와 실행하는 과정이다.
이때 CPU가 메모리로부터 명령어와 데이터를 가져오기 위해 두가지 종류의 버스(bus)가 필요하다.
(버스는 '와이어' 라고 하는 도체 선들의 묶음으로 이해하자.)
1. Address Bus
명령어와 데이터를 가져올 메모리의 위치(주소) 정보를 주고 받는 버스
2. Data Bus
Address Bus에 적힌 주소에서 가져온 데이터를 주고 받는 버스
2가지 버스를 통해 명령어와 데이터를 가져오고 (Fetch), 실행하고 (Execute), 필요에 따라 메모리에 쓰는 동작을 반복하는 것이 Stored Program Concept 이다.
MIPS Instruction Category
MIPS를 포함한 대부분의 CPU의 명령어는 다음과 같이 분류된다.
- 데이터 처리 명령어 (산술 명령어 / 논리 명령어)
- 메모리 접근 명령어 (Load, Store)
- 분기 명령어 (Branch)
산술 명령어를 예시로 들면 MIPS는 다음과 같은 문법으로 산술 명령어를 처리한다.
add a, b, c → a 라는 목적지에, b와 c를 더한 결과를 저장해라
뺄셈, 곱셈, 나눗셈 등 다른 산술 명령어도 위와 같은 format을 가진다.
(format: 피연산자의 개수와, 순서)
MIPS에서는 덧셈을 오직 위와 같은 형식의 명령어 하나로만 지원한다.
x + y + z 와 같이 3개를 더해서 저장하는 명령어는 존재하지 않는다.
기존의 명령어를 여러번 활용하여 수행해야 한다.
이는 위에서 정리한 RISC Design Principle 에서 '단순하게 만들려면 규칙적으로 만들어라' 에 따르는 내용이기도 하다.
(모든 산술 명령어는 정확히 3개의 피연산자를 가진다. 더 많이도, 적지도 않다.)
산술 연산자의 피연산자는 '레지스터' 라고 하는 CPU 내부 저장공간을 가리켜서 데이터를 가져오거나,
상수 값 (immediate field) 을 바로 사용할 수 있다.
Register
- CPU 안에 있는 저장 공간으로, MIPS는 32bit 크기의 레지스터를 32개 가지고 있다.
(레지스터 하나의 크기는 CPU가 다루는 명령어/데이터의 크기와 같으며, 이것이 32-bit / 64-bit 버전을 결정한다.)
각각의 32bit 레지스터는 flip-flop 32개를 이용하여 구현한다.
(실제로는 크기를 더 줄이기 위해 레지스터 대신 SRAM을 사용한다)
32개로 적은 수의 레지스터를 갖는 MIPS는 위에서 정리한 '작을수록 빠르다' 는 원칙에 입각한 설계이다.
- Registers are visible to the programmers
어셈블리에서 어떤 레지스터에 데이터를 저장할지 프로그래머가 명시할 수 있다.
- 레지스터는 CPU와 가까워 데이터를 읽고 쓰는 속도가 빠르다. (레지스터 > 캐시 > 메모리)
하지만 가격이 비싸고 CPU 내부에 공간이 많지 않으므로 다른 저장장치에 비해 용량이 적은 것이 특징이다.
컴파일러는 효율적으로 프로그램을 실행하도록 하기 위해, 컴파일 시 데이터를 저장할 때 메모리보다 레지스터에 저장하도록 변수 공간과 레지스터를 매핑하는 것이 중요하다.
Register File
레지스터들의 집합을 가리켜 Register File 이라고 부른다.
register file에 접근할 때는 register file을 둘러싸고 있는 껍질을 통과해야하는데, 껍질을 통과할 때는 반드시 'port' 를 거쳐서 통과해야한다.
MIPS의 reigster file은 2개의 read port 와 1개의 write port를 가지고 있다.
(산술 명령어는 3개의 피연산자를 받는데, 2개는 연산할 레지스터이고, 1개는 저장할 레지스터이다.)
먼저 레지스터의 값을 읽는 동작을 보자.
그림에서 src1 addr 는 register file 안으로 들어가고 있다.
이때 숫자 5는 5개의 와이어 묶음이라는 뜻이다.
하나의 와이어가 하나의 bit 데이터를 전송하므로, 5개 와이어로는 5bit 데이터를 전송할 수 있다.
데이터의 크기가 5bit 인 이유는 레지스터의 개수가 32개 2^5 개 이기 때문이다.
위 그림 상단을 보면 src1 addr의 5bit 값을 통해 레지스터 하나를 특정하여 32bit 값 src1 data를 읽는 것을 나타내고 있다.
마찬가지로 src2 addr의 5bit 값으로 레지스터 하나를 특정하면, 해당 레지스터의 32bit 값 src2 data가 나온다.
레지스터에 값을 쓰는 동작을 살펴보자.
레지스터에 값을 쓸 때는, 데이터를 쓸 레지스터의 addr 정보와 어떤 값을 쓸 지 명시하는 data 정보가 필요하다.
register file 좌측 하단을 보면 dst addr, wirte data 정보가 들어오는 것을 볼 수 있다.
여기에 더해 MIPS는 write control 이라는 추가적인 값을 활용하여 쓰기를 진행한다.
결국 컴퓨터도 기계인지라, 전기 신호가 초기에 0, 1이 무작위로 세팅되어 있을 수 있다.
이 무작위 값을 register file에 자칫 잘못 쓰는 일이 없도록, write control 이 1 일 때만 값을 쓰도록 제한하고 있다.
(읽기 동작의 경우, 무작위 값을 읽는다고 해서 register file에 변화가 발생하지 않기 때문에 별도 control이 없다.)
MIPS Assembler Register Names
MIPS는 register file에 있는 32개 레지스터 각각에게 역할에 맞는 이름을 지어줬다.
그 중에 먼저 위 사진에 나와있는 8번부터 25번 레지스터를 먼저 살펴보자.
설명에 나와있는 것처럼 MIPS는 10개의 temporary value 용 레지스터 공간과, 8개의 saved value 용 레지스터 공간을 제공한다.
각 번호별 레지스터에 접근하기 위한 어셈블리상 코드는 $t0 ~ $t9, $s0 ~ $s7 이다.
t-register는 최종적으로 필요한 연산결과를 얻는 과정에서 발생하는 중간 연산 결과를 저장하는 용도로 사용하고,
s-register는 입력으로 주어지는 변수 속 데이터와, 최종 연산 결과 값을 저장하는 용도로 사용한다.
(컴파일러도 소스코드를 번역할 때 최대한 이에 맞춰 어셈블리 코드로 변환하도록 한다.)
Memory Hierarchy
컴퓨터의 메모리는 계층 구조를 가지고 있다.
MIPS의 메모리도 마찬가지다.
순서대로 나열하면 아래와 같다.
Register File > L1 Cache > L2 Cache > L3 Cache > Main Memory > Secondary Storage
뒤로 갈수록 속도는 느려지지만, 저장 용량은 커지고 가격은 저렴해진다.
Register File은 CPU 코어 안에 들어있다.
L1 ~ L3 캐시는 CPU 코어 바깥에 있지만 CPU에 합쳐져 있는 On-Chip Components 이다.
Levels of Program Code
High - Level language
인간에게 제일 가까운 언어. 생산성과 이식성이 좋다.
똑같은 코드를 컴파일러만 맞추면 하드웨어에 상관없이 실행시킬 수 있기 때문
( one - to - many 관계 )
Assembly language
기계어를 글자로 1:1 매핑시킨 언어 ( one to one 관계 )
MIPS 는 어셈블리 언어이므로 portable 하지 않다. ( 기출 )
Machine code (object code / binary)
컴퓨터가 직접 이해할 수 있는 언어
'CS > 컴퓨터 구조' 카테고리의 다른 글
[컴퓨터 구조] 6. MIPS Branch Instructions (0) | 2024.04.15 |
---|---|
[컴퓨터 구조] 5. MIPS Data Transfer Instructions (2) (0) | 2024.04.14 |
[컴퓨터 구조] 4. MIPS Data Transfer Instructions (1) (0) | 2024.04.06 |
[컴퓨터 구조] 3. MIPS Arithmetic & Logical Instruction (0) | 2024.04.06 |
[컴퓨터 구조] 2. Clock & Verilog (0) | 2024.04.06 |