Architecture
우리가 흔히 말하는 architecture와 컴퓨터시스템의 architecture와는 조금 다르다.
아키텍쳐의 정의: “the attributes of a system as seen by the programmer, the conceptual structure and functional behavior”
간단히 얘기하자면 소프트웨어와 하드웨어사이를 보이게 하는 interface이다. Interface의 예로 키보드, 마우스등이 있다. 하지만 여기서 얘기하는 interface는 instruction이다. Instruction을 통해서 소프트웨어가 하드웨어를 작동시키는 원리다.
User(OS, compiler..)는 기계가 어떤원리로 작동하는지 알아야한다. 하지만 우리는 깊게는 알 필요가 없다. 예를 들어서 add라는 operand가 010100이런식으로까지 알 필요는 없다.
정리하자면 컴퓨터 아키텍쳐는 하드웨어와 소프트웨어의 abstracted interface이다.
ISA는 다음것들을 포함한다. Instruction set, operand types, data types, memory addressing modes
컴퓨터 아키텍쳐는 레지스터와 other state, the interrupt/exception model. Memory management and protection, virtual physical address layout, I/O mode 등등 도 정의한다. 이것들의 특징은 모두 visible한 것이다. 그리고 이것들이 컴퓨터 아키텍쳐를 구성한다.
마이크로아키텍쳐는 internals and invisible part이다. Clock frequency, pipeline/cache configurations(캐시는 접근 조차도 불가능,address도 없음), number/location of functional units, programmer transparent techniques: prefetching..같은기술들이 마이크로아키텍쳐의 일부이다.
마이크로아키텍쳐보다 더 밑에 있는 부분이 implementation이다. Implementation은 hardware realization(실현)이다. 예를 들어서 cpu cache를 만든다고 하면 어떻게 만드는지가 implementation issue이다.
아키텍쳐 vs 마이크로아키텍쳐(fear.ARM)
Arm은 cpu회사가 아니라 cpu design회사이다. 여태까지 많은 ARMv? 시리즈의 아키텍쳐를 만들어왔다. 마이크로아키텍쳐가 서로 달라도 같은 프로그램을 실행할 수 있다. 근데 아키텍쳐 자체가 다르다면 호환이 되지 않음.
Operations of Computer Hardware
Instruction set
Instruction set은 cpu가 어떠한 종류의 instruction을 제공하는지 알 수 있다. Different architecture는 다른 instruction sets을 가지고 있다. 하지만 instruction sets들은 많은 부분이 비슷하다. 초기의 컴퓨터들은 기술이 부족한 관계로 굉장히 적은 instruction sets을 가지고 있었다 60~80개 정도. 그리고 지금도 어떠한 컴퓨터는 조금의 instruction sets을 지원한다. 물론 어떤 컴퓨터는 굉장히 많은 instruction sets을 지원한다. 여기서 많은 instruction을 지원하는 것이 CISC. 적은 것이 RISC이다. RISC는 ARM, MIPS, PowerPC등이 있다. RISC 사용자들은 간단한 instruction set으로 빠르고 효율적으로 perform 할 수 있다고 생각하고 CISC 사용자들은 더 좋은 기술들로 더 복잡한 CPU를 만들 수 있다고 생각한다. 그러면 프로그램이 더 줄어들고 이로 인해서 더 빠르게 실행할 수 있다고 생각한다. 하지만 둘은 절대적일 수 없고 이 둘의 적절한 조화속에 만들어진다.
근래에 ARM이 제일 많이 팔리는 아키텍쳐이다. 왜냐하면 ARM이 스마트폰,자동차,TV, 테블릿pc등에 장착되어 있기 때문이다.
The MIPS Instruction set
하지만 반전인 것은 이 수업에서는 MIPS instruction set을 배운다는 것이다.
Mips가 임베디드 시장에서는 많이 사용된다. Mips도 ARM과 마찬가지로 cpu의 디자인을 판매한다. Mips를 배우는 이유는 굉장히 일반적이고 단순하기 때문이다. 이걸 배우면 다른 아키텍쳐도 배우기 쉽기 때문이기도 하다.
Arithmetic Operations
Add a, b, c # a gets b+c
3개의 operands, a = b+c이다. 모든 arithmetic operations가 이러한 형식을 가지고 있다. 대부분 a는 결과값을 저장하는 메모리 어드레스 또는 레지스터이다.
여기서 우리는 mips 디자인의 첫번째 원칙을 알 수 있다. “simplicity favors regularity”(간단하기 위해서는 규칙적인 것이 좋다.) 왜 그럴까? 규칙은 circuit를 간단하게 하기 때문이다. 모든 instruction이 같은 format을 가지고 있으면 복잡한 instruction decoding 유닛은 필요가 없어진다. 간단히 말하자면 회로가 간단해짐으로 더 빨리 수행이 가능하다. 결론적으로 간단한 회로로 higher clock frequency를 가질 수 있게 되고 그럼으로 higher performance를 보여준다.
Arithmetic Example
f=(g+h)-(i+j)
add t0, g, h #temp t0 = g+h
add t1, i, j #temp t1 = i+j
sub f, t0, t1 #f=t0-t1
Operands of Computer Hardware
Register Operands
Arithmetic instructions들은 register operands를 사용한다. MIPs는 32개의 32비트 레지스터 파일을 사용한다. 그럼으로 버스의 width는 32비트가 될것이다, 이러한 시스템을 32-bit system이라고 한다. 그리고 32비트 데이터를 “word”라고 부른다. 근데 intel에서 분명히 word는 16비트라고 했는데 이는 backward compatibility. 1970년 처음 16비트가 만들어졌을 때는 intel은 word를 16비트로 만들었다. 하지만 1980년대 32비트를 런칭하고 인텔 그 이전세대의 프로그램들이 새로워진 환경속에서도 실행이 될 수 있게 이전에 설정한 word를 남기고 double word를 만들었다. 이로 인해서 이전 세대의 프로그램도 최신환경에 돌아가게 한것이다. 64비트에서는 quad word를 만들기도 했다.
$t0, $t1, … ,$t9 for temporary value, $s0, $s1, …, $s7 for saved variables to bring the data stored in memory to the CPU.
2번째 원칙: smaller is faster 메모리는 겁나 크지만 레지스터는 32*32비트이다.
Memory operand
int와 fp는 primitive data이다. 그래서 더 이상 쪼개질 수 없는 형태이다. 그리고 c언어에서 이 primitive data들을 조합해서 배열이나, 구조체, 동적할당을 통해서 새로운 형태를 구성할 수 있다. 이러한 타입을 composite data type이라고 한다. 그래서 메인메모리는 주로 composite data를 저장한다.
Arithmetic operation을 사용하기 위해서 값을 메모리에서 레지스터로 로드해야한다. Mips에서는 모든 operand는 must be in register file. 이와 같이 결과는 다시 레지스터에서 메모리로 이동시켜야 한다. 왜냐하면 arithmetic operations는 결과값을 메모리 address에 저장할 수 없기 때문이다.
메모리는 바이트식으로 지정된다 즉 8비트가 한 address의 단위이다. 메모리에 있는 데이터에 접접근 할 때에는 해당 데이터 주소의 주변 4바이트와 함께 접근을 해야한다. 왜냐하면 버스의 width 크기가 32비트이기 때문이다. 그래서 한번에 적어도 4바이트를 로드해야한다. 그리고 이 주소의 시작 값은 알고자 하는 데이터 주소값의 4배가 된다.
Mips는 빅인디안이다.
Byte Addressed
8비트 즉 1바이트는 굉장히 유용하다 왜냐하면 c언어에서의 primitive data의 최소단위가 1바이트이기 때문이다(char 같은 경우). 위에서 말한 것과 같이 메모리를 접근하기 위해서 해당 메모리 주소값의 4배를 가지고 와야한다 이러한 alignment restriction을 따르지 않을 경우 속도가 2배가량 느려진다.
MIPs와 ARM은 RISC이다
Memory Operand Example1
g=h+A[8];
-g는 $s1, h in $s2, base address of A in $s3
Mips Code:
lw $t0, 32(offset)($s3(base register))
add $s1, $s2, $t0
Memory Operand Example2
A[12]=h+A[4];
-h in $s2, base address of A in $s3
Mips Code:
lw $t0, 16($s3)
add $t0, $s2, $t0
sw $t0. 48($s3)
Register vs Memory
기본적으로 모든 데이터는 메모리에 저장된다. 하지만 데이터를 사용하기 위해서 기본적으로 메모리의 데이터를 로드해 레지스터에 옮긴다. 레지스터에 옮겨진 데이터는 최대한 길게 남아져야 한다 그 이유는 지속적으로 메모리에 왔다갔다하는 것은 오래걸리기 때문이다. 하지만 레지스터는 작아서 오직 몇몇의 데이터만을 가지고 있을 수 있다. 그래서 어떠한 데이터들은 다시 메모리에 store해야 한다. 이러한 과정을 register spiling이라고 한다. 그래서 컴파일시 컴파일러는 적게 사용하는 데이터를 지정해 메모리에 store시킨다. 이러한 결정들은 register optimization라고 한다.
Immediate Operands
Immediate는 constant이다. i=i+4 같은 경우 addi $s3, $s3, 4가 된다. 원래는 메모리 어딘가에 있는 상수를 로드해야하지만 addi같이 operand에 i를 붙여서 굳이 로드를 하지 않아도 된다.
RISC 아키텍쳐에서 immediate operand를 사용하는 것은 cpu designer에게 굉장히 어렵다. 왜냐하면 RISC는 앞서 말한 것 때문에 (간단하기 위해서는 규칙적인 것이 좋다)모든 instruction은 32비트의 메모리 공간을 가져야만한다. 하지만 만약에 immediate이 정말 말도 안되게 큰 수가 들어와서 심지어 32비트보다 큰 데이터가 들어오게 된다면 이는 큰 낭패이다. 실제로 immediate operand들은 12~8비트만을 차지한다. 만약에 큰 숫자가 오게 된다면 그 데이터는 먼저 메모리에 저장이 되고 사용될 때 레지스터에 로드된다. 그리고 작은 숫자면 그냥 encoded instruction에 저장된다.
레지스터 0번째의 값$zero은 언제나 0이다. 그래서 로드 할 필요가 없이 매우 유용하게 사용할 수 있다.
$zero나 immediate operand를 통해서 알 수 있는 세번째 디자인 원리는 “Make the common case fast”이다. 작은 값의 상수들은 load를 하지 않으므로 프로그램을 short해지며 더 빠르게 작동하게 된다.
'시스템프로그램' 카테고리의 다른 글
[컴퓨터구조개론] 4. Integer Arithmetic (2) | 2020.10.19 |
---|---|
[컴퓨터구조개론] 3. MIPs Instruction and Set Architecture(2) (0) | 2020.10.18 |
[컴퓨터구조개론] 1. Computer abstraction and technology (0) | 2020.10.17 |
[시스템프로그램]03-1-1 Program encodings(1) (0) | 2020.05.02 |
[시스템프로그램]02-3-3 실수와 사칙연산(3) (4) | 2020.04.30 |
댓글