ARM System Developer's Guide  

- Designing and Optimizaing System Software




#####

C Looping Structures - summary

Register Allocation

Function Calls




### 5.3. 속도 향상을 고려한 C 루프문


> Summary <

효과적인 루프문의 코딩


1. 0으로 다운카운트하는 루프문 사용.

컴파일러는 최종값을 저장하기 위해 레지스터를 할당 할 필요가 없음

0과의 비교작업에 비용이 들지 않음


2. default로 unsigned loop count를 사용하고 반복조건은 i>0보다 i!=0을 사용

루프 오버헤드는 명령어 2개로 줄어듬


3. 루프가 적어도 한 번 이상 실행된다면 do-while 사용

컴파일러가 루프 카운터가 0인지 아닌지를 체크할 필요성을 없애줌


4. 루프 오버헤드를 줄여야 하는 중요한 루프문은 unrolling. (너무 많이 해서도 안됨)

루프 오버헤드가 전체의 일정 비율만큼 작아지면 언롤링은 코드 사이즈를 증가시킴

즉, 캐시 성능에 좋지 않음


5. 배열에서 element의 수는 4나 8의 배수가 되도록 정렬

배열의요소를 추가해야 할 지에 대한 고민하지 않고 루프를 2,4,8배로 쉽게 언롤릴 할 수 있음.




### 5.4. ATPCS에서의 레지스터 매핑


> 효육적인 함수 구현

- spilled(swapped out)되는 변수의 수를 최소화

- 가장 중요하면서 자주 액세스되는 변수들을 레지스터에 저장하도록 함



> 효율적인 레지슽 할당

1. 이론적으로 C 컴파일러는 14개의 변수를 레지스터에 저장할 수 있으나, 실제 몇몇 컴파일러들은 임시 스크래치 작업을 위해 r12같은 고정된 레지스터를 사용하고 있음.

또 복잡한 표현식 계산을 위해 임시 작업용 레지스터들을 필요로 함

=> 함수 내부 루틴에서 사용하는 지역 변수의 수를 12개로 제한하도록 하자.

2. 변수들이 내부 루프에서 사용되고 있는지를 확인하여 중요한 변수를 컴파일러에게 알리도록 하자.




### 5.5. 서브루틴 호출시 매개변수 처리


- APCS(ARM Procedure Call Standard) : 함수 인자와 리턴값을 ARM register로 보내는 방법에 대하여 정의

- ATPCS(ARM-Thumb Procedure Call Standard) : ARM과 Thumb interworking도 다루고 있음



- 처음 4개의 정수 인자는 ARM레지스터의 처음 4개인 r0,r1,r2,r3에 저장

- 다음의 정수 인자는 full descending stack에 저장

- 함수 리턴은 r0으로 보내짐

- long long, double과 같은 두 워드는 인접한 쌍의 연속된 레지스터로 보내지며, 리턴값은 r0, r1로 보내짐

- 구조체를 보낼 수도 있음


# PCS

1. four-register rule

: 4개 또는 그 이하의인자를 가지는 함수에서 모든 인자가 레지스터에 저장될 수 있어 효율적임

C에서 4개의 인자나, C++에서 3개이상의 외부인자가 필요할 경우 구조체가 더 효율적임

(구조체 포인터를 패싱하도록)


2. 작은 함수들은 같은 소스파일 안에 이들을 호출하는 함수 앞에 정의.

: 컴파일러는 함수 호출을 최적화 하거나 작은 함수들을 인라인 시킴, C 컴파일러는 호출될 함수를 위해 생성된 코드를 알 수 있게되어 호출할 함수 안에서 최적화가 가능


- caller는 callee가 중복되지 않는다는 것을 알 수 있어 레지스터들 보존이 필요 없음. 

caller는 ATPCS에서 중복 가능한 레지스터들을 저장할 필요가 없음

- callee가 매우 작다면 컴파일러는 호출하는 함수 안에 그 코드를 인라인 시켜 함수 호출 오버헤드를 완전히 없애줌


3. 크리티컬한 함수는 __inline 키워드로 Caller함수에 인라인 시킴. 

- 단순 정보를 주는 힌트일 뿐 컴파일러가 컴파일 할 때 사용하지는 않음.

- 큰 함수를 인라인 시키는 것은 성능향상에  별 도움이 안되며 코드 사이즈만 증가시키게 됨




'System > Embedded' 카테고리의 다른 글

[ARM] 익셉션과 인터럽트 처리 2  (0) 2015.11.10
[ARM] 익셉션과 인터럽트 처리  (0) 2015.11.10
[ARM] 32비트 ARM 명령어 2  (0) 2015.11.09
[ARM] 32비트 ARM 명령어  (0) 2015.11.09
[ARM] ARM 프로세서 개요 2  (0) 2015.11.09

ARM System Developer's Guide  

- Designing and Optimizaing System Software




#####

Data Processing instructions

Branch Instructions

Load-Store Instructions

Software Interrupt Instructions

Program Status Register Instructions

Loading Constants

ARMv5E Extensions

Conditional Execution





### 3.4. SWI 명령어

- Software Interrupt Instructions

- Software Interrupt Exception을 발생시키는 명령어

- Applications이 OS routin을 호출하기 위한 mechanism으로 사용


- "pc = vectors + 0x8" : 프로세서 모드를 "SVC"로 변경하여 OS routin이 특권모드로 호출될 수 있도록 함

- SWI_number : 특정 함수의 호출이나 특징을 나타냄




### 3.5. PSR 명령어

- Program Status Register Instruction

- ARM 명령어 세트는 PSR을 직접 제어하기 위해 MRS, MSR 명령어를 제공

MRS : cpsr이나 spsr의 내용을 레지스터로 전송

MSR : 레지스터의 내용을 cpsr이나 spsr으로 전송



* fields : control(c), extension(x), status(s), flag(f)의 어떤 조합으로 구성


- c fields : 인터럽트 마스크, Thumb 상태, 프로세서 모드를 제어어


> 예제 3.26에서 I 마스크를 클리어 하여 IRQ 인터럽트를 활성화 시키는 방법

1. MSR 명령어로 cpsr값을 r1로 복사

2. BIC 명령어로 r1의 7번째 비트를 0으로 클리어

3. r1을 cpsr로 복사하여 IRQ interrupt를 활성화

* cpsr의 다른 모든 설정값은 유지. control영역의 I 비트만 수정



## 3.5.1. 코프로세서 명령어

- Coprocessor Instruction

- 명령어세트를 확장하기 위해 사용

- 추가의 게산능력을 제공해주거나 캐시와 메모리 관리 장치를 포함한 메모리 서브시스템을 제어하기 위해 사용

- 데이터처리 명령어, 레지스터 전송 명령어, 메모리 전송 명령어

=> 코프로세서에 특화



- cp field : p0에서 p15 사이의 코프로세서의 수

- opcode field : 코프로세서 상에서 발생하게 될 동작

- Cn, Cm, Cd field : 코프로세서 안의 레지스터들을 의미미

- Coprocessor 15(CP15)는 메모리 관리장치, 쓰기버퍼제어, 캐시제어, 고유 레지스터 할당(identification registers) 같은 시스템 제어를 위해 할당됨



## 3.5.2. 코프로세서 15 명령어 표기법 

- Coprocessor 15 Instruction Syntax

- CP15 : 프로세서 코어를 설정하고 설정정보를 저장하기 위한 전용 레지스터 세트를 가짐

=> "시스템 컨트롤 코프로세서"

- MRC와 MCR 명령어로 CP15를 read/write

- Rd : 코어 결과 레지스터

- Cn : 기본 레지스터

- Cm : 보조 레지스터

- opcode2 : 보조레지스터를 수정하는 용도

- 확장 레지스터라는 보조 레지스터가사용되기도 함


"MCR    p15,                    0,                r1,                    c1,                                c0,    0"

"MCR 코프로세서 번호, 무조건 0, 레지스터번호, Coprocessor의 레지스터번호, c0, 무조건0"


=> 간략한 표기법

"CP15:cX:cY:Z"


"CP15    :                    cX    :                                            cY    :                                                            Z"

"코프로세서 번호, 기본레지스터(X:0-15사이의 값), 보조레지스터or확장레지스터(Y:0-15사이의 값), opcode2(0-6)"



참고.  http://dreamlog.tistory.com/221




### 3.6. Loading Constants

: 상수값 로드

: ARM 명령어 세트에서 32-bit 상수값을 레지스터에 저장하는 명령어는 없음

=> 명령어는 32-bit 이기때문에, ARM명령어가 32비트의 상수값을 포함할 수 없음


=> 2가지 의사명령어를 제공하여 ARM은 32-bit value를 레지스터에 저장할 수있게함 (플밍이 쉬워짐)



- LDR : 가능한 명령어들의 조합을 이용하여 32비트값을 레지스터에 저장

만약 상수값을 다른 명령어들의 조합으로 만들 수 없을 땐, 메모리를 직접 액세스하여 읽음

- ADR : 상대 주소를 레지스터에 저장. pc 상대 주소 표현법을 사용하여 해석

pc 상대 덧셈, 뺄셈을 이용하여 주어진 레이블의 주소를 레지스터 Rd에 저장


> 32비트 상수값 0xff00ffff를 레지스터 r0으로 읽는 LDR 명령어

-----------------------------------------

LDR    r0,    [pc,    #const_number-8-{pc}]

.

const_number

DCD    0xff00ffff

-----------------------------------------

- 상수값 로드를 위해 메모리에 액세스 (시간에 민감한 루틴에서는 큰 손실이 발생)


> MVN 명령어를 이용하여 상수 0xff00ffff를 레지스터 r0에 로드

-----------------------------------------

PRE        none...


 MVN    r0,    #0x00ff0000


POST    r0 = 0xff00ffff

-----------------------------------------


- 컴파일러와 어셈블리는 가능한 메모리에서 상수값을 로드하는 걸 피하기 위한 테크닉을 사용

- 한 레지스터안에서 상수값을 만들고, 배럴 시프터를 사용해 확장시키는데 필요한 최적의 명령수를 찾는 알고리즘을 가짐

-  LDR 명령어는 상수값을 만들기 위해 MVN, MOV 명령어를 삽입하거나,

 코드내에 literal pool에서 상수값을 읽기위해 pc 상대 주소를 갖는 LDR 명령어를 만들어 냄


# 의사 명령어의 변환


1. MOV 명령어를 만듬

2. pc상대 주소를 이용한 LDR 명령어를 생성




### 3.7. ARMv5E Extensions

- 새로운 많은 명령어들을 제공

- signed MAC 명령어 : 16비트 데이터를 가지고 처리가 가능한 곱셈계산 명령어로 16비트 데이터조작에 유연성과 효율성을 제공

* MAC : Multiply Accumulate

* 16비트 데이터 조작은 16비트 디지털 신호 처리와 같은 applications를 위해 중요한 요소


- 많은 ARMv5E 제품군에서는 MAC 명령어들이 한 사이클에 실행


> ARMv5E에서 제공하는 새로운 명령어



## 3.7.1. CLZ 명령어

- Count Leading Zeros Instruction

- 최상위 비트에서 처음으로 1이 나온 비트 사이에 0이 몇개나 있는가를 세는데 사용


> Example 3.30 <


PRE        r1 = 0b00000000000000000000000000010000    ; 0이 27번 나온 후 1이 나옴

CLZ    r0,    r1

POST    r0 = 27


* 정규화 루틴에서 유용함


## 3.7.2. 포화 산술 연산

- Saturated Arithmetic

- 보통의 ARM 산술 연산 명령에서는 32비트 정수값에 오버플로우가 발생하면, 제대로된 처리를 못함

ex. 0x7fffffff + 1 = -0x80000000


=> ARMv5E의 명령어를 사용하여 결과값을 포화시킴. 오버플로우가 발생하면 결과는 가장 큰 정수값으로 저장(0x7fffffff)

(오버플로우 체크를 위해 추가적인 코드가 필요없어짐)




## 3.7.3. ARMv5E 곱셈 명령어


- x,y : 32비트 레지스터에서의 첫번째 16비트를 사용할지, 두번째 16비트를 사용할지 선택

상위 16비트 : "T"

하위 16비트 : "B"

- 32bit의 결과를 생성하는 MAC연산에서 Q flag는 덧셈결과(signd 32bit value)에 오버플로우가 발생했는지의 여부를 나타냄

- 향상된 곱셈 명령어는 16비트값의 곱셈에서 나은 유연성을 제공



### 3.8. 조건부 실행

- 대부분의 ARM명령어는 조건부로 실행이 가능

- 주어진 조건이나 task 상황을 만족 할 때만 명령어가 실행되도록 설정해야 함

- 조건부 명령어의 사용은 성능 및 코드의 직접도를 향상

- AL(always) 조건문자 : 명령어 니모닉뒤에 붙어 항상 실행하라는 의미를 가짐


- 조건부의 실행은 분기 상황을 감소시켜 파이프라인이 깨지는 수를 줄여줌

=> 코드의 성능 향상

- 조건 필드와 상태 플래그에 영향을 받음

조건필드 : 명령어상에 위치

상태플래그 : cpsr


- 특정한 알고리즘을 수행하는 데 필요한 명령어의 수를 상당량 줄여줌



'System > Embedded' 카테고리의 다른 글

[ARM] 익셉션과 인터럽트 처리  (0) 2015.11.10
[ARM] 최적화된 C프로그래밍  (0) 2015.11.10
[ARM] 32비트 ARM 명령어  (0) 2015.11.09
[ARM] ARM 프로세서 개요 2  (0) 2015.11.09
[ARM] ARM 프로세서 개요  (0) 2015.11.09

ARM System Developer's Guide  

- Designing and Optimizaing System Software




#####

Data Processing instructions

Branch Instructions

Load-Store Instructions

Software Interrupt Instructions

Program Status Register Instructions

Loading Constants

ARMv5E Extensions

Conditional Execution





> ARM은 버전에 따라 지원하는 명령어들이 다르지만 하위 호환성을 보장

> 어떤 명령어들은 기능 확장으로 mnemonic이 변경되기도 함

> ARM 명령어는 register안에 들어있는 데이터를 처리

> load-store 명령어만 가지고 메모리 액세스

> 2개 or 3개의 오퍼랜드를 가짐

> 명령어는 4가지로 분류

- Data Processing 명령어

- branch 명령어

- load-store 명령어

- Software interrupt 명령어




### 3.1. Data Processing Instructions


- 레지스터 안에서 데이터를 조작하는데 사용

- 데이터 이동 명령어, 산술 명령어, 논리 명령어, 비교 명령어, 곱셈 명령어

- 대부분의 데이터 처리 명령어에서 오퍼랜드 중 하나를 barrel shifter를 사용하여 처리가 가능

- "S" 접미사 : 명령어 처리 후 결과를 가지고 cpsr 플래그들을 업데이트

- 데이터 이동 연산과 논리연산 후 상태 플래그 업데이트

C : carry. barrel shifter의 결과, 시프트되어 나온 마지막 비트값으로 설정

N : nagative. 결과값의 31번째 비트 값으로 설정

Z : zero. 결과가 0인경우 설정


## 3.1.1. 데이터 이동 명령어

- N 값을 결과 레지스터인 Rd에 복사

* N : 레지스터 값 혹은 상수 값

- 초기값 설정이나 레지스터간에 데이터를 이동하기 위해 사용


## 3.1.2. Barrel Shifter

: 데이터 처리 명령어는 ALU에서 처리되는데, 데이터 처리의 효율을 목적으로 ALU로 입력되기 전 배럴 시프터에 의해 2진 단위의 좌우 시프트가 가능하게 함

-> 많은 데이터 처리 명령어의 강력함가 유연성이 증진


> N : 일반 상수값 or 레지스터값 or 데이터 처리 명령어에 의해 사용기 전 배럴 시프터로 미리 시프트 처리를 한 레지스터 Rm 


> barrel shifter를 사용할 수 없는 데이터 처리 명령어

: MUL(multiply), CLZ(Count Leadming Zero), QADD(signed saturated 32-bit add)



- 선처리나 시프트 작업은 한 명령어의 실행 사이클 내에서 처리

-> 상수 값을 레지스터로 로드하여 2의 거듭자리 만큼 곱하거나 나누기를 할 때 유용함


* LSL : C언어에서의 시프트 연산자 (<<)


# Barrel Shifter에서 사용할 수 있는 5가지 시프트연산

* carry flag : 1 



예제. 

* shift 해서 계산 후, 명령어에 S가 붙어있으므로 상태플래그 캐리비트 활성화



## 3.1.3. Arithmetic Instructions

산술명령어. 32-bit signed/unsigned 값의 덧셈/뺄셈을 구현하기 위해 사용


* ?????, 예제 3.6에서 상태플래그 중 Carry는 왜 1로 설정?



## 3.1.4. 산술 연산에서의 배럴 시프터 사용


* 산술 연산이나 논리 연산에서 두 번째 오퍼랜드의 시프트가 가능하는 점은 ARM 명령어 세트에서 매우 강력한 특징



## 3.1.5. Logical Instructions

> 논리 명령어는 2개의 소스 레지스터에 비트단위로 논리 연산을 수행



* ?????, BIC 예제 잘 이해 안됨. 물어보기.


## 3.1.6. Comparison Instructions

: 32-bit 값을 가진 레지스터를 비교하고 테스트 하기위해 사용


- cpsr 플래그 비트를 업데이트 하며, 다른 레지스터에는 영향을 미지치 않음

- 해당 비트들을 세트한 후, 조건부 실행을 사용해 프로그램의 흐름을 변겨하는데 사용

- 접미사 "S"가 필요하지 않음



* 비교 명령어는 비교되는 레지스터에는 영향을 끼치지 않음.

오직 cpsr의 상태 비트만 업데이트. 



## 3.1.7. Multiply Instructions

: 곱셈명령어. 두 레지스터 안의 내용을 곱하는 명령어


- 명령어에 따라 곱한 결과에 또 다른 값을 더하기도 함

- 62-bit 곱셈명령어(long multiply)는 64비트를 표현하는 2개의 레지스터를 이용하여 곱셈

결과는 하나의 결과레지스터에 저장 or 2개의 레지스터를 이용해 저장


- 곱셈 명령어를 실행하는 데 걸리는 사이클 수는 프로세서마다 다름

- 어떤 프로세서에서는 실행 사이클이 Rs 안에 저장되어 있는 값에 따라 다름


> 64-bit 곱셈 명령어(SMAL, SMULL, UMLAL, UMULL)를 수행하면 64-bit의 결과가 나옴

but, 결과는 32-bit 레지스터에 저장해야 하는데 크기때문에 문제가 됨

=> RdLo, RdHi라는 레이블이 붙은 2개에 레지스터에 각각 결과중 하위 32bits, 상위 32bits가 저장



### 3.2. Branch Instructions

: 실행의 흐름을 변경하거나 어떤 루틴을 호출하는 데 사용


- subroutines, if-then-else 구조, loops 사용이 가능하도록 해줌

- PC가 새로운 주소를 가리키도록 함으로써 실행의 흐름을 바꿈


# ARMv5E 명령어 세트의 4가지 분기 명령어

- label이 가리킼는 주소는 "signed PC - 상대 offset"의 형태로 명령어에 저장

- 분기 명령어의 약 32MB 이내의 주소여야 함

- T : cpsr의 Thumb bit

- BL : 링크값을 갖는 분기로써, LR로 복귀할 주소를 저장하며 서브루틴 호출을 수행하는데 사용

- BX : Thumb 코드로 분기하기 위해 레지스터 Rm에 있는 절대 주소값을 사용

BLX : BX와 유사하며, 최하위 비트값으로 cpsr의 T 비트를 업데이트. 추가로 LR를 복귀할 주소를 저장




### 3.3. Load-Store Instructions

: 메모리와 프로세서 레지스터 사이에서 데이터를 전송


- Single-Register Transfer

- Single-Register Load-Store Addressing Modes

- Multiple-Register Transfer



## 3.3.2. 단일 레지스터 전송 명령어

- Single-Register Transfer

- 메모리->레지스터, 레지스터->메모리, 하나의 데이터를 전송하는데 사용

- 지원되는 데이터형 : signed/unsigned words(32-bit), halfwords(16-bit), bytes(8-bit)

* addressing1, addressing2 : 표 3.5, 표 3.6  참고


- LDR과 STR 명령어는 load되거나 store되는 데이터형 크기와 똑같은 배열로 데이터를 load/store 할 수 있음

(ex. LDR은 0, 4, 8 등으로 메모리 주소상에 32비트 워드를 load할 수 있음)


*예제 3.15. 


; 레지스터 r1이 가리키는 메모리 주소의 내옹을 r0에 로드

LDR    r0,    [r1]        ; LDR    r0,    [r1, #0]


; 레지스터 r0이 가리키는 메모리 주소의 내용을 r1이 가리키는 메모리 주소에 저장

STR    r0,    [r1]        ; STR    r0,    [r1,    #0]


> #0 : offset, r1 : base address register



## 3.3.2. 단일-레지스터 로드-스토어 주소지정방식

- Single-Register Load-Store Addressing Modes

- ARM 명령어 세트는 메모리 주소의 계산을 위해 다양한 모드를 제공하며, 

이 모드는 preindex with writeback, preindex, postindex이라는 indexing methonds 중 하나를 포함하고 있음


* !는 명령어가 계산된 주소를 베이스 주소 레지스터에 저장한다는 의미


* 자동인덱스, 프리인덱스, 포스트인덱스로 변역되어 있음


# 자동인덱스

- auto index

- preindex with writeback

- 베이스 레지스터로부터의 주소에서, 주소 offset만큼을 계산한 후 새로운 주소값으로 베이스 레지스터를 업데이트

- 배열을 검색하는데 사용


# 프리인덱스

- 베이스 레지스터로부터의 주소에서, 주소 offset만큼을 계산한 후 주소 베이스 레지스터를 업데이트 하지는 않음

- 배열을 검색하는데 사용


# 포스트인덱스

- 주소가 사용된 후 주소 베이스 레지스터를 단지 업데이트만 수행 함

- 데이터 구조 안의 요소들을 액세스 하기위해 사용


> Example 3.16 <


pre    r0 = 0x00000000

  r1 = 0x00009000

  mem32[0x00009000] = 0x01010101

  mem32[0x00009004] = 0x02020202


LDR    r0,    [r1,    #4]!


Preindexing with writeback : 

POST[1]    r0 = 0x02020202

 r1 = 00009004


LDR    r0,    [r1,    #4]


Preindexing : 

POST[2]    r0= = 0x02020202

          r1 = 0x00009000


- LDR    r0,    [r1],    #4


Postindexing : 

POST[3]    r0 = 0x01010101

  r1 = 0x00009004


# 32-bit 워드 또는 unsigned 바이트의 load-store를 위해 사용할 수 있는 주소지정방식


- 특별한 load-store 명령어를 사용할 수 있는 주소지정방식은 명령어군에 따라 달라짐

- signed offset or register는 +/- : base address register Rn으로부터의 음/양수 offset

- immediate : base address register + offset(12-bit)을 통해 계산된 주소

- scaled : base address resister + barrel shift를 통해 계산된 주소


# 각각 다르 주소지정방식을 사용한 LDR 명령어의 예


# 단일 레지스터 로드-스토어 주소지정방식, 하프워드, signed 하프워드, signed 바이트, 더블워드

: 16-bit halfword나 signed byte data를 사용하여 load-store 명령어 상에서 사용할 수 있는 주소지정방식


* Table 3.6, Table 3.7의 동작들은 barrel shifter를 사용할 수 없음

- STRH는 signed/unsigned halfword를 둘 다 저장할 수 있어, STRSB나 STRSH가 존재하지 않음

* ????, STRH면 haftwork를 다루는건데, 왜 STRSB같은 바이트를 다루는 명령어를 여기서 이야기 할까

STRB에서 거론해야하는거 아닌가... ? 


# 다양한 STRH 명령어들



## 3.3.3. 다중-레지스터 전송 명령어

- Multiple-Register Transfer

- 명령어 하나로 메모리와 프로세서 사이에서 여러개의 레지스터를 전송

- 전송은 메모리를 가리키는 base address register에서 발생

- 인터럽트 발생 시, 다중-레지스터 전송명령어가 완료 될 때가지 인터럽트가 지연되므로 인터럽트 지연시간을 증대시킬 수 있음

* armcc와 같은 컴파일러는 전송할 레지스터의 최대수를 제어하여, 최대 인터럽트 지연시간을 제한


# 다중 로드-스토어 명령어를 위한 여러가지 주소지정 방식 (*N : 레지스터 리스트 안에 포함된 레지스터의 수)

: 메모리 배열의 앞쪽, 뒤쪽을 액세스가 가능하게 됨 (Stack의 push, pop)


> Example 3.17 <


"LDMIA    r0!,    {r1-r3}"

- "r0" : base register, Rn

- "!" : 명령어 실행 후 Rn에 update

- "-" : 레지스터 범위. 물론 열거해도 됨

- "{}" : 괄호안에 레지스터 각각을 열거해도 됨


- r0은 전 상태에서 메모리 주소 0x80010을 가리킴

- 메모리 주소 0x80010, 0x80014, 0x80018은 각각 1,2,3의 값을 가짐


> LDM명령이 수행된 후 각 r1, r2, r3는 1,2,3 값을 가지게 됨

- base register가 같는 주소는 업데이트 되어 0x8001c를 가짐


> "LDMIB는 Increment Before"

: base address register의 값을 미리 증가를 시킨 후 명령을 수행 ?


> DA, DB는 "decrement"

- 시작 주소를 감소시킨 후 그위의 메모리 영역에 저장

- 메모리 주소의 감소가 아니라 레지스터 리스트가 반대 순서로 액세스 함


# base address가 업데이트 될 때 사용되는 LDM-STM의 쌍

- 레지스터의 값을 임시로 저장하고 복구할 때 유용


> Example 3.18 <  


----------------------------------------

PRE         r0 = 0x00009000

r1 = 0x00000009

r2 = 0x00000008

r3 = 0x00000007


STMIB    r0!,    {r1-r3}


MOV    r1,    #1

MOV    r2,    #2

MOV    r3,    #3

----------------------------------------

- "IB" , "Rn!"이므로

r0의 주소값은 Rn + 4 * N = r0(0x00009000 + 4 * 3) = 0x0000900c 로 없데이트

- r1, r2, r3의 값인 9,8,7을 메모리에 저장

- MOV 명령어로 각각 1,2,3으로 업데이트

----------------------------------------

PRE2       r0 = 0x0000900c

r1 = 0x00000001

r2 = 0x00000002

r3 = 0x00000003


LDMDA    r0!,    {r1-r3}

----------------------------------------

- 레지스터 리스트가 반대 순서로 액세스하며 원래 값을 다시 읽음

- DA로 시작주소를 감소

r0 = Rn - 4 * 3 = 0x0000900c - 12 = 0x00009000

"!"이 있으므로 r0값을 업데이트

----------------------------------------

POST       r0 = 0x00009000

r1 = 0x00000009

r2 = 0x00000008

r3 = 0x00000007

----------------------------------------


> Example 3.19 <  

: 블록메모리 복사를 위한 다중-레지스터 전송 명령어의 사용. 32bytes 복사하기


; r9 - 소스데이터의 시작 위치

; r10 - 결과 데이터의 시작 위치

; r11 - 쓰의 끝 위치


Loop

; 소스의 위치부터 r0-r7(4bytes * 8 = 32bytes)를 로드하여 r9을 업데이트 (복사할 다음 블럭의 위치를 저장해야하므로 "!")

LDMIA    r9!,    {r0-r7}


; 결과데이터를 32bytes 저장하고 r10 업데이트 (결과를 저장할 다음 목적지 영역을 저장해야하므로 "!")

STMIA    r10!,    {r0-r7}


; 소스의 끝인지 체크

CMP    r9, r11     ; r9, r11을 비교

BNE    loop        ; Branch Not Equal. CMP 명령어가 상태 플래그를 not equal로 설정하면 분기 명령어 실행

   ; 업데이트 된 상태명령어가 not equal이 아니면 루틴이 끝남



# 3.3.3.1. Stack Operations


- 다중-레지스터 전송 명령어를 사용

- Pop : LDM, Push : STM

- ascending 스택 : 스택을 메모리 상위 주소 뱡향으로 증가

  descending stack :스택을 메모리 하위 주소 방향으로 증가

- full stack(F) : sp에 마지막으로 사용된 위치 저장(마지막 아이템)

  empty stack(E) : sp에 처음 사용되지 않은 위치를 저장(마지막 아이템 다음의 빈공간)


- stack 동작을 지원하기 위한 다양한 다중-레지스터 전송 주소지정방식이 있음

- ARM에서는 루틴의 호출과 레지스터들의 할당을 ATPCS에 정의하고 있음

* ATPCS : ARM-Thumb Procedure Call

- ATPCS에서 stack을 full descending stack으로 정의

- pop, push를 LDMFD, STMFD 명령어로 구현


> 스택 동작을 위한 어드레싱 방법


> STMFD 명령어 : full stack push 동작과 empty stack  push 동작



> Stack 처리를 위해 보존해야하는 3가지 인자

- Stack Base : 메모리 상에서 스택의 시작 위치

- Stack Pointer : 초기에는 스택 베이스를 가리키지만 데이터가 스택으로 들어가면 메모리 하단으로 이동하며 스택의 가장 맨 위를 계속 가리킴

- Stack Limit : 스택 포인터가 스택 리미트를 넘어가면 Stack Overflow가 발생


* Stack Overflow의 체크


SUB    sp,    sp, #size

CMP    sp,    r10

BLLO_stack_overflow        ; 조건


- ATPCS에서는 r10 레지스터를 "sl(stack limit)"으로 정의

- BLLO : 분기 명령어 "BL"  +  조건인자 "LO" 

=> sp가 r10보다 작으면 overflow 발생

=> sp가 stack base보다 작아질 때도 오버플로우 발생



## 3.3.4. Swap Instruction

: 메모리의 내용과 레지스터의 내용을 바꾸어주는 명령어


- 단일 수행 명령어

: 명령어의 처리가 끝날 떄까지 다른 명령어가 그 영역을 read/write 하지 못하도록 같은 버스를 사용해 어떤 영영을 read/write 함

=> "버스를 잡고있다."라고 표현


- OS안에서 세마포어나 뮤텍스 구현에 유용함

- 표기법에서 인자B(바이트 단위를 나타냄)를 사용할 수 있기때문에, 워드나 바이트 단위의 데이터 교환에 유용








'System > Embedded' 카테고리의 다른 글

[ARM] 최적화된 C프로그래밍  (0) 2015.11.10
[ARM] 32비트 ARM 명령어 2  (0) 2015.11.09
[ARM] ARM 프로세서 개요 2  (0) 2015.11.09
[ARM] ARM 프로세서 개요  (0) 2015.11.09
[ARM] ARM 임베디드 시스템  (0) 2015.11.08

ARM System Developer's Guide  

- Designing and Optimizaing System Software




#####

ARM processor core

Data movement flow

Programmer's model from SW developer's view (processor core <-> differnt parts)

ARM core naming conventions, ARM Instruction Set Architecture

ARM processor core families




### 2.6. Architecture Revisions


# ISA 

: Instruction Set Architecture


# ARM 프로세서는 특정 ISA로 구현됨



## 2.6.1. 명명법

"ARM + 해당 프로세스가 갖는 특징"


- ARM7TDMI 이후의 모든 ARM 코어는 TDMI가 생략되어 있는 것임

- family(제품군)은 동일한 하드웨어 특징을 보이는 프로세서집합을 의미

- JTAG는 IEEE1149.1 Standard Test Access Port and Boundary Scan Architecture에서 정의하고 있으며, 
    프로세서 코어와 테스트 장비간의 디버깅 정보를 전송하기 위해 ARM에서 적용한 시리얼 포트

- EmbeddedICE macrocell : 프로세서에 내장되어 있는 디버기 하드웨어 장치. (breakpoint, watchpoint 제공)

- synthesizable : 프로세서 코어가 EDA 툴에 의해 쉽게 사용 가능한 형식으로 컴파일 될 수 있는 소스코드로 공급된다는 것을 의미



## 2.6.2. 아키텍처의 발전


- ARMv4(ARM7TDMI)에서의 Thumb 명령어 세트의 지원

- 참고. 

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.set.architecture/index.html

http://infocenter.arm.com/help/topic/com.arm.doc.dui0204ik/Cegbgefe.html




### 2.7. ARM Processor Familes

(ARM 프로세서의 버전별 특징)


- ARM7, ARM9, ARM10, ...

- 7,9,10,... 과 같은 숫자들은 코어 종류를 의미

- 숫자들은 제조 과정의 환경에 직접적으로 영향을 받기때문에 크게 달라 질 수 있음

(제조환경은  MHz, W에 직접적 영향을 주기때문)

- 각 ARM 제품군 안에는 Memory Management Device, cache, TCM Processor등이 다양하게 내장 

(제품군의 수와 각 제품군내에서 다른 적용 제품들을 계속하여 확장함)

- ARM ISA를 실행할 수 있는 다른 프로세서들 - StrongARM, XScale (intel과 같은 특정 반도체 회사에 특화되어 개발)



*  table 2.8에서 "all"

: ARMv4 아키텍처와 그 이후의 버전에서 가능하다는 것을 의미



## 2.7.1. ARM7 Family

- 폰노이만 형태를 가지는 버스 아키텍처

- 3단 파이프라인 

- ARMv4T 명령어 셋


> ARM7TDMI (1995)

- Thumb  instruction set 지원

- fast multiply instructions

- EmbeddedICE Debug technology



> ARM7TDMI-S

- ARM7TDMI + synthesizable


> ARM720T

- MMU를 포함 - 리눅스나 마이크로소프트 임베디드 OS를 사용할 수 있음

- ARM7 제품군 중에 유연성이 가장 뛰어남

- 통합된 8K의 캐시를 포함

- Vector Table은 CP15 레지스터 값을 설정하여 상위 주소로 위치를 변경할 수 있음


> ARM7EJ-S

- synthesizable

- 유일하게 ARM7 제품군 중, 5단 파이프라인을 포함

- ARMv5TEJ 명령어를 실행시킬 수 있음

- ARM7 제품군 중 유일하게 Java 가속기와 DSP 확장 명령어를 제공

- without MPU



## 2.7.2. ARM9 Family

- ARM9 (1997)

- 5단 파이프라인 : ARM7보다 빠른 클럭 속도로 동작

- 하버드 형태의 버스 아키텍처 (데이터 D Bus + 명령어 I Bus)


> ARM920T

- 하버드 형태의 캐시 아키텍처

- MMU 내장

- 가상메모리 지원

- v4T 명령어


> ARM922T

- ARM920T의 변종

- D+I 캐시의 크기가 절반으로 줄어듬


> ARM940T

- 보다 작은 D+I 캐시

- MPU 내장

- 플랫폼 OS를 필요로 하지 않는 Applications를 위해 설계

- v4T 명령어


> ARM9E-S 코어

- ARM9 코어의 다음 프로세서 코어

- E 확장자가 붙은 ARM9 코어의 synthesizable 버전

- 제품 : ARM946E-S, ARM966E-S

- 두 제품 모두 v5TE 명령어, 옵션으로 ETM(Embedded Trace Macrocell)지원하여 시간에 민감한 Applications를 디버깅 할 때 용이함.


* ETM(Embedded Trace Macrocell)

: 프로세서에서 실시간으로 데이터와 명령어를 검사할 수 있는 기술


ARM946E-S

- TCM, 캐시, MPU

- TCM, 캐시의 크기 조절 가능

- 확정적 실시간 응답성을 요구하는 임베디드 제어 Applications에서 사용하기 위해 설계


ARM966E-S

TCM, 크기 조절 가능


> ARM926EJ-S (2000)

- ARM9 제품군 중 마지막으로 발표된 코어

- 3G, PDA 등 작고 휴대 가능한 java를 지원하는 장치를 위해 설계

- Jazelle. java 코드 가속화 가능

- MMU, 조절 가능한 TCM, D+I 캐시


## 2.7.3. ARM10 Family


> ARM10 (1999)

- 성능 향상이 목적

- 6단계의 파이프라인

- VFP(Vector Floating-Point) 장치를 지원

=> 파이프라인의 7번째 단계로 추가 가능


* VFP - 부동소수점 성능을 대폭 향상, IEEE754.1985 부동소수점 표준과 호환


> ARM1020E

- ARM10 코어의 첫번째 프로세서

- ARM9E처럼 향상된 E 명령어들을 포함

- 32K의 하버드 형태의 캐시 D + I

- 선택적으로 추가가능한 VFP 및 MMU

- 듀얼 64-bit Bus Interface 지원 (성능향상도모)

 

> ARM1026EJ-S

ARM926EJ-S과 비슷

- MPU, MMU 둘다 포함

ARM926EJ-S의 유동성과 ARM10의 성능을 모두 갖춤



## 2.7.4. ARM11 Family


> ARM1136J-S (2003)

- 고성능, 저전력의 Applications를 위해 설계

- 아키텍처 ARMv6 명령어로 구현된 첫번째 제품군

- 8단 파이프라인 (load-store 파이프라인과 산술파이프라인의 분리)


* ARMv6명령어에는 SIMD 확장 명령어가 포함되어 있음

(SIMD : Single Instruction Multiple Data. 미디어처리, 비디오 처리 능력을 향상할 수 있음)


> ARM1136JF-S

- 빠른 부동소수점 계산을 위해 ARM1136J-S에 VFP 장치를 포함



## 2.7.5. 이외에 특별한 제품군


> StrongARM 

- Digital Semiconductor사와 합작으로 개발된 제품

- 현재 Intel에서 라이센스를 가짐

- 저전력 소모 및 고성능을 필요로하는 PDA와 Applications에서 인기

- 하버드 형태의 캐시 아키텍처

- 5단 파이프라인을 적용한 최초의 고성능 ARM 프로세서

- Thumb 명령어는 지원하지 않음


> XScale

- Intel

- StrongARM의 다음 버전

- 성능을 대폭 개선

- 아키텍처 v5TE 명령어를 실행

- 하버드 아키텍처

- StrongARM과 유사

- MMU 내장


> SC100

- 저전력 보안 장치를 위해 설계한 코어

- 첫번째 SecurCore 제품

- ARM7TDMI를 기반으로 구현

- MPU 내장

- 적은 전압과 전류를 필요로 함

- 스마트카드 및 Applications에 응용할 수 있음






'System > Embedded' 카테고리의 다른 글

[ARM] 32비트 ARM 명령어 2  (0) 2015.11.09
[ARM] 32비트 ARM 명령어  (0) 2015.11.09
[ARM] ARM 프로세서 개요  (0) 2015.11.09
[ARM] ARM 임베디드 시스템  (0) 2015.11.08
[ARM] 참고 + ARM 아키텍처의 미래  (0) 2015.11.08

ARM System Developer's Guide  

- Designing and Optimizaing System Software




#####

ARM processor core

Data movement flow

Programmer's model from SW developer's view (processor core <-> differnt parts)

ARM core naming conventions, ARM Instruction Set Architecture

ARM processor core families



# Dataflow and ARM core's abstract components

> 폰노이만 형태로 구현된 ARM 모델

Von Neumann implementations : 데이터와 명령어가 같은 버스를 공유하는 형태

  Harvard implementations : 데이터용 버스와 명령어용 버스가 분리되어있는 형태


> Data : Data Bus를 통해 core로 입력

> Instruction decoder : 명령어 실행 전 명령어 해독

> Load-Store Architecture 

load 명령 : 메모리에서 코어내의 레지스터로 데이터를 복사

store 명령 : 레지스터에서 메모리로 데이터를 복사

* 메모리 안에서 데이터를 직접 조작할 수 있는 데이터 처리 명령어는 없으므로 레지스터 안에서만 수행할 수 있음

> Register file : 32비트 레지스터들로 구성된 저장공간

메모리에서 읽은 signed 8-bit or 16-bit 값은 register에 저장되기 전 "Sign Extend(부호 확장기)"를 통해 32-bit 값으로 변경된 후 저장

> Two source registers & Single result register

Two source registers : Rn(Bus A, *barrel shifter), Rm(Bus B)

Single result register : Rd

*barrel shifter 선처리 작업 수행

> ALU(Arithmetic Login Unit, 산술논리장치) & MAC(Multiply-Accumulate Unit, 곱셈누산장치)

: Bus A와 B에서 각각 Rn, Rm register의 값을 읽어 연산을 수행

: Rd 레지스터에 저장된 결과를 결과버스를 통해 register files에 바로 저장



### 2.1. Registers

- 데이터나 주소가 저장



- 16개의 Data registers[r0-r15]와 2개의 Status registers로 구성

- 한번에 18개까지 활성화 가능


> 특수 목적을 갖는 레지스터

- r13 :  SP(Stack Pointer). 현재 모든 프로세서 모드의 스택 맨 위 주소값 저장 

- r14 : LR(Link Register). 코어가 서브루틴을 호출할 때마다 그 복귀주소를 저장

- r15 : PC(Program Counter). 프로세서가 읽어들인 다음 명령어의 주소를 저장


* r13, r14는 범용 레지스터로도 사용하며 프로세서 모드가 바뀌면 뱅크에 저장되므로 특히나 유용하게 사용할 수 있음

but, r13은 OS에서 유효한 스택 프레임을 가리키고 있는 것으로 가정하여 동작하므로 위험함


> 상태레지스터

- cpsr : Current Program Status Register. 현재의 프로그램 상태 레지스터

- spsr : Stored Program Status Register. 이전에 저장된 프로그램 상태 레지스터




### 2.2. CPSR 

: Current Program Status Register. 현재의 프로그램 상태 레지스터


- ARM core 내부 동작 모니터링 및 제어

- 전용 32-bit register. Register file안에 위치



* 8-bit씩, 4개의 영역으로 나뉨.    

" Flag(8-bit), Status(8-bit), Extension(8-bit), Control(8-bit) "


- 부록 B



## 2.2.1. Processor Modes

: 어떤 레지스터가 활성화되고, cpsr를 액세스 할 수 있는 권리를 갖게 될지 결정

Privileged Mode : 특권모드. cpsr을 완전히 읽고 쓸 수 있는 모드

- User Mode : 일반모드. cpsr의 제어 필드는 읽기만 가능, 상태 플래그 필드는 읽기/쓰기 모두 가능


> Seven Processor's Modes

six privileged modes, single user mode


 abort mode

 프로세서가 메모리 액세스에 실패한 경우 진입 

 Privileged Mode

 FIQ & IRQ mode 

 ARM 프로세서에서 사용할 수 있는 2가지의 입터럽트 레벨을 위한 모드 

 supervisor mode 

 프로세서에 리셋이 걸렸을 때 진입하여 OS Kernel이 동작하는 모드 

 system mode  

 user mode의 특수한 버전으로 cpsr의 완전한 read/write이 가능 

 undefined mode

 프로세서가 정의되지 않거나 지원되지 않는 명령어를 만났을 때 진입하는 모드 

 user mode 

 프로그램과 어플리케이션이 동작하는 모드 

 User Mode



## 2.2.2. Banked Registers



*왼쪽 흰색 부분에서 

[r0-r12] : 일반적으로 CPU에서 "load-store" 명령어를 가지고 사용하는 레지스터

r13 sp, r14 lr, r15 pc, cpsr


* 회색 부분 : 프로세서의 특정 모드에따라 사용이 가능하게 되며, 해당 프로그램에 따라 매번 숨겨짐


- Banked registers는 user mode registers에 하나씩 대응

- 프로세서 모드 변경 시 새로운 모드의 banked registers로 대체됨

* 프로세서 모드는 HW의 interrupt나 exception, 혹은 cpsr을 직접 제어하여 변경

(exceptions - reset, interrupt request, fast interrupt request, software interrupt, data abort, prefetch abort, and undefined instruction)


# 익섹셥시 모드 변경


- user mode -> irq mode


- r13, r14가 r13_irq, r14_irq로 뱅크되어 대체됨

r13_irq : 복귀할 주소를 포함

r14_irq : IRQ mode를 위한 SP 저장


* user mode의 r13, r14는 어떤 명령에 의해서도 영향을 받지 않음


- spsr_irq : 이전 모드의 cpsr을 저장하며 irq모드에서만 보여짐

user mode로 돌아가기 위해 spsr_irq에서 cpsr을 복구시켜 주는 특별한 리턴 명령어 사용


* spsr은 특권모드에서만 read/write 할 수 있으므로, user모드에서의 액세스는 불가능


> ?????

: 그림에서 spsr_irq의 색은 왜 하얀색인가?


# Processor mode


# spsr. cpsr의 저장

: cpsr은 interrupt나 exception 발생에만 저장이 됨. cpsr의 직접 제어로 인한 모드변경에서는 저장되지 않음


# Mode bits

- Figure 2.3에서 cpsr의 하위 5비트는 프로세서 모드를 나타냄

- Table 2.1에서 맨 오른쪽 열인 "Mode[4:0]"이 해당 모드를 각각 나타내는 비트패턴


* 코어에 전원이 공급되면 해당 Mode bit을 "supervisor"로 시작됨

이 모드는 특권모드이므로 cpsr을 완전히 액세스 할 수 있음

=> 초기화 코드가 다른 모드들을 위한 스택을 셋업할 수 있게되는 것.



## 2.2.3. State and Instruction Sets


- ARM 명령어 세트 : 프로세서가 ARM 상태에 있을 때만 활성화

- Thumb 명령어 세트 : 프로세서가 Thumb 상태에 있을 때만 활성화. 순수한 16-bit Thumb 명령어만 실행

- Jazelle 명령어 세트 : Java Virtual Machine을 수정한 버전.

Jazelle의 하드웨어 일부분에서 java코드를 지원해야하며 나머지는 소프트웨어적으로 에뮬레이션 됨

table 2.3


* ARM, Thumb, Jazelle 명령어 세트를 섞어서 사용할 수 없음


> cpsr의 Jazelle J, Thumb T ? 프로세서의 상태를 반영함

- J와 T가 0인 경우 :  프로세서는 ARM 상태에 있으며 ARM 명령어를 실행하고 있음. (전원이 공급되는 순간은 항상 ARM 상태)

- T비트가 1인 경우 : Thumb 상태


* 코어의 상태를 바꾸기 위해서는 특별한 분기 명령어가 필요 table 2.2




## 2.2.4. Interrupt Masks

: 특정 인터럽트 소스가 프로세서에게 인터럽트 요청을 할 수 없도록 하는 것

ARM 프로세서 코어에서 가능한 인터럽트 요청 레벨에는 IRQ와 FIQ의 2가지가 있음


> ex. cpsr - 2개의 인터럽트 마스크 비트 

6번(F) : 1일때, FIQ의 인터럽트를 마스크

7번(I) : 1일때, IRQ의 인터럽트를 마스크



##  2.2.5. Condition Flags


> 상태 플래그 업데이트

- 비교명령어에 의한 업데이트

- 산술 명령어 뒤에 "S"가 붙은 경우 산술 처리 결과에 따라 업데이트

  : "subs" -> 뺄셈 명령어의 결과 레지스터에 0이 저장되면 cpsr의 Z(zero) 플래그가 1로 설정


- DSP 확장 명령어를 포함하는 프로세서 코어의 경우,

Q 비트가 오버플로우나 포화가 발생하였는지 표시하며 "sticky"하며 0으로 플래그값을 설정하려면 cpsr의 값을 직접 수정해야 함

* sticky : 하드웨어에 의해서만 플래그가 1로 설정될 수 있음을 의미.


- Jazelle를 지원하는 프로세서에서 J비트는 코어의 상태를 반영 함(1인경우 Jazelle 상태라는 것을 의미)

Jazelle를 사용하고자 할 경우 몇몇 프로세서 코어에서만 사용이 가능하며, ARM Limited와 Sun Microsystems로부터 라이센스를 받아야 함




- 대부분의 ARM 명령어는 상태 플래그 값에 따라 조건부로 실행이 가능

- cpsr의 최상위 비트에 위치



- DSP와 Jazelle를 지원

- nzCvq -> C만 대문자인 이유는 플래그 값이 1임. 플래그 값이 1일 때는 대문자로 표현

* 인터럽트의 경우, 대문자는 인터럽트 비활성을 의미


- j와 t가 0이므로 Jazelle와 Thumb가 0. -> ARM 상태에 있음

- IRQ interrupt : 0(활성화), FIQ1(비활성화)

- SVC : Mode[4:0]이 supervior 모드임을 의미



## 2.2.6. Conditional Execution


- 조건부 실행 : 코어가 어떤 명령어를 실행할 지의 여부를 제어할 있음

- 조건 인자를 통해 명령어 실행여부를 결정

- 명령어는 조건인자를 가지고 있음

- 조건인자는 명령어 mnemonics 바로뒤에 추가되어 명령어와 함께 incode 됨

- 명령어 실행 전 core는 자신이 가지고있는 조건인자와 cpsr의 상태플래그를 비교

일치하면 명령어 실행, 일치하지 않으면 명령어는 무시됨

- 조건인자가 없다면 "AL"으로 설정되어 항상실행 됨



* mnemonic?

: 연상기호. 일반적으로 무엇인가를 연상하여 기억하기 위해 만들어진 짧은 코드들을 의미. 이러한 기억방법을 개발하는 기술을 "mnemonics"라고 부름름

: 어셈블리 언어에서는 연상기호는 연산 명령어를 줄여서 만들어 놓은 것

각 어셈블러 명령어의 연산 코드 필드에 사용

  출처. http://www.terms.co.kr/mnemonic.htm




### 2.3. Pipeline

- RISC Processor가 명령어를 실행하기 위해 사용하는 메커니즘

- 한 명령어가 해독되어 실행되는 동안, 다음 명령어를 미리 읽어올 수 있도록 함으로써 실행속도를 향상


# 3단 파이프라인의 구조


- Fetch : 메모리에서 명령어를 로드

- Decode : 실행한 명령어를 해독

- Execute : 명령어를 처리하고 그 결과를 레지스터에 저장




- "Filling the Pipeline" : 매 사이클마다 하나의 명령어를 실행시킬 수 있도록 해줌줌


> 파이프라인의 길이가 길어지면, 

1. 프로세서는 더 많은 동작 주파수를 필요로하며 각 단계에서 처리 가능한 일의 양이 감소

=> 성능 향상. but, 명령어를 실행하기 전 파이프라인을 채우는 시간이 길어지므로 시스템 지연도 발생

2. 각 단계의 데이터가 서로 영향을 끼침. 의존관계

=> 의존도를 줄이기 위해 "명령어 스케줄링(6장)"을 이용


# ARM 제품군에 따른 파이프라인 설계


> ARM9

- 5단계 : "Memory", "Write(writeback)" 추가

- 결과 : MHz당 평균 1.1 Dhrystone MIPS를 처리

ARM7에 비하여 13%의 명령어 처리 능력이 향상


> ARM10

- 6단계 : "Issue" 추가

- 결과 : MHz당 평균 1.3 Dhrystone MIPS를 처리

ARM7에 비하여 34%의 명령어 처리 능력이 향상. but, 지연시간이 길어짐



* ARM7, ARM9, ARM10은 모두 "Pipeline executing characteristics(파이프라인 동작 특성)"를 사용하고 있음

-> ARM7에서 작성된 코드는 ARM9나 ARM10에서 그래도 실행 가능



## 2.3.1. Pipeline Executing Charateristics


- ARM Pipeline은 어떤 명령어가 실행 단계로 넘어오기 전까지는 그 명령어를 처리하지 않음

즉, 3단게를 가진 ARM7 파이프 라인에서는 4번째 명령어가 읽혀들어 올 때 쯤에야 하나의 명령어가 수행 됨



> ex. MSR : IRQ Interrupt 활성화 명령어

실행 단계에서 cpsr의 I비트를 0으로 설정

ADD 명령이 실행단계로 오면 IRQ Interrupt가 활성화 됨



> 파이프라인과 PC의 사용

- 실행 단계에서 PC는 항상 명령어의 주소(0x8000)에 8을 더한 값을 가리킴

즉, PC는 현재 실행되고 있는 명령어의 주소보다 2단계 앞서 값을 가지고 있음

(PC의 offset값 계산에 중요한 요인)

* Thumb 상태에서 pc는 "명령어주소+4"



# 파이프라인의 세가지 특성

1. 분기 명령어로 실행되거나 PC값을 직접 수정하여 분기하면 파이프라인이 깨짐

2. ARM10은 분기 예측방식을 사용.

명령어를 실행하기 전에 가능한 분기를 미리 예측하여 새로운 분기 주소를 로드하여 파이프라인이 깨지는 상황을 줄여줌

(하드웨어적으로 자주가는 곳을 미리 기억)

3. 실행 단계의 명령어는 인터럽트가 발생하더라도 해당 명령의 수행은 완료함.

파이프라인 안의 다른 명령어들은 무시되고, vector table에 적절한 엔트리 명령어로 파이프라인을 채움




### 2.4. Exceptions, Interrupts, and the Vector Table

(ARM 프로세서에서의 exceptions)


> Exceptions이나 Interrupt가 발생한 경우, 

프로세서는 "Vertor Table"에서 해당 exceptions이나 interrupts를 처리하도록 이미 설계가 되어있는 특정 루틴으로 분기하는 특정 메모리의 주소값을 PC에 설정


# 분기 명령어

 Reset vector

 전원이 공급될 때 프로세서에 의해 처음으로 실행되는 명령어의 위치. 

 초기화 코드로 분기. 

 Undefined Instruction vector 

 프로세서가 명령어를 분석할 수 없을 때 사용 

 Software Interrupt vector

 SWI 명령어를실행했을 때 호출

 * SWI : 운영체제 루틴에서 벗어나고자 할 경우 주로 사용 

 Prefetch Abort vector

 프로세서가 정확한 접근 권한 없이 어떤 주소에서 명령어를 읽어들이려고 시도할 때 발생

 (실제 abort는 파이프라인의 decode단계에서 발생) 

 Data Abort vector

 Prefetch Abort와 유사

 명령어가 정확한 접근권한이 없이 데이터 메모리를 액세스 하려고 할 때 발생 

 Interrupt Request vector

 프로세서의 현재 프름을 중단시키기 위해 외부 하드웨어 장치에 의해 사용됨.

 IRQ가 cpsr에서 마스크 되지 않았을 경우만 발생 

 Fast Interrupt Request vector

 IRQ와 유사하나 더욱 빠른 응답 시간을 요규하는 하드웨어를 위해 할당.

 FIQ가 cpsr에서 마스크 되지 않았을 경우만 발생 





### 2.5. Core Extensions (캐시 메모리와 코프로세서)

: ARM 코어 주변에 확장 시킬 수 있는 하드웨어 장치


- 표준 컴포넌트

- 성능 향상, 자원 관리, 추가 기능 제공

- 캐시 및 TCM(Tightly Coupled Memory), MMU, Co-processor Interface



## 2.5.1. 캐시와 TCM


# 캐시

: main memory와 core 사이에 위치하는 빠른 메모리 블럭으로 효율적인 fetch를 가능하게 함


# ARM기반 시스템의 캐시

- 프로세서 내부에 1단계 캐시를 이용

- 폰노이만 형태의 캐시 구조 vs 하버드 형태이 캐시 구조


> Von Neumann 형태의 구조

: 데이터와 명령어를 하나의 통일된 캐시에 함께 저장


* Logic and control : 로직제어장치. 메모리 시스템을 AMBA 버스에 연결해주는 논리 장치


> Harvard 형태의 구조

: 명령어와 데이터를 위한 캐시가 각각 분리되어 있음


캐시는 성능은 향상시키지만, 예측성을 떨어뜨릴 수 있음. 

특히 실시간 시스템에서 이런 코드 실행의 확정성(deterministic)의 문제는 큰 이슈가 됨

=> TCM으로 해결


> TCM 

- Tightly Coupled Memory

- 코어 가까이에 빠른 SRAM을 위치하여 명령어나 데이터를 읽을 때 필요한 클럭 사이클을 보장

(확정적 동작에 필요한 실시간 알고리즘을 위해 필수적으로 필요한 클럭사이클)


> 캐시 + TCM 구조

: 성능향상과 예측 가능한 실시간 응답을 보장



## 2.5.2. 메모리 관리

> 임베디드 시스템에서는 여러 개의 메모리 소자를 사용하므로 이를 체계적으로 관리하고,

 하드웨어로 부적적하게 접근하는 어플리케이션으로부터 시스템을 보호해야 함

=> 메모리 관리 하드웨어 사용


# 3가지 유형의 메모리 관리 하드웨어

 일반 관리 장치 (no extensions providing no protection)

 - 비보호 메모리. non-protected memory

 - 고정적, 유연성 없음

 - Applications로부터의 보호를 필요하지 않는 작고 간단한 임베디드 시스템에서 사용

 제한적인 보호를 제공하는 메모리 보호 장치 (MPU)

 - 제한된 수의 메모리 region을 사용하는 간단한 시스템에 적용

 - 특별한 코프로세서 레지스터를 사용하여 제어

 - 각 영역은 특정 권한으로 정의

 - 메모리 보호는 필요하지만 복잡한 memory map구조는 사용하지 않는 시스템에서 사용

 (13장)

 완전한 보호를 제공하는 메모리 관리 장치 (MMU)

 - ARM에서 사용되는 가장 복잡한 메모리 관리 장치

 - mapping table set을 제공

 - main memory에서 저장되어 접근권한 및 가상메모리 mapping을 수행

 - multi tasking 시스템을 위해 설계

 (13장)



## 2.5.3. Coprocessor

코어의 처리 기능을 확장하기 위해 ARM 프로세서에 부착하여 사용

- 명령어세트의 확장, 값을 설정할 수 있는 레지스터를 제공

- 인터페이스를 통한 하나이상의 코프로세서를 추가할 수 있음

- load-store 타입의 인터페이스를 제공해주는 전용 ARM 명령어 사용


> ex. Coprocessor 15(CP15)

: TCP, MMU의 제어를 위해 CP15 레지스터를 사용


- 새로운 특정 명령어들을 제공하여 명령어 세트 확장이 가능    

=> decode 단계에서 처리

ex. decode 단계에서 coprocessor의 명령어 발견

-> 명령어가 관련 coprocessor로 이동

만약, coprocessor가 없다면? "Undefined Instruction Exception" 발생

-> 소프트웨어적으로 coprocessor의 동작을 에뮬레이션 할 수 있음 

> ????? 그럼 이 예외처리는 당연히 OS가 하는건가??





'System > Embedded' 카테고리의 다른 글

[ARM] 32비트 ARM 명령어  (0) 2015.11.09
[ARM] ARM 프로세서 개요 2  (0) 2015.11.09
[ARM] ARM 임베디드 시스템  (0) 2015.11.08
[ARM] 참고 + ARM 아키텍처의 미래  (0) 2015.11.08
스토리지 시스템  (0) 2015.08.13

ARM System Developer's Guide  

- Designing and Optimizaing System Software




# ARM  ? 

ARM 유한회사(Adbanced RISC Machines)는 RISC 프로세서를 설계하고 라이센싱하는 회사로,

ARM 아키텍처는 ARM사에 의해 개발한 CPU 디자인의 한 종류이다.

(wiki)


# ARM Architecture ?

ARM 아키텍처는 임베디드 기기에서 많이 사용되는 RISC 프로세서이다. 저전력을 사용하도록 설계하여 ARM CPU는 모바일 시장에서 뚜렷한 강세를 보인다.

- 1985년 4월 26일 영국의 캠브리지에 있는 에이콘 컴퓨터(Acorn Computers)에 의해서 탄생.

- 1990년 11월에 애플과 VLSI의 조인트 벤처 형식으로 Advanced RISC Machines Ltd.)가 생김

(wiki)




### 1.1. RISC의 특징


# RISC 

 : 매우 빠른 속도로 한 클럭안에 실행 될 수 있는 간결하면서도 막강한 명령어들을 가지고 있는 아키텍처를 의미


# RISC vs CISC

 

 RISC 

 CISC 

 Full Name

 Reduced Instruction Set Computer

 Complex Instruction Set Computer 

 Focus on

 Software

 Hardware 

 Depend on

 Compiler

 Hardware

 Hardware Complexity

 decrease

 increase


# RISC의 4가지 Design rules

1. Instructions : 명령어의 복잡도를 줄여 성능을 향상


- 적은수의 명령어 클래스를 가짐

- single cycle에서 실행가능한 simple operations 제공

- simple operation 몇 개를 조합하여 복잡한 연산(나눗셈 연산 등)들을 구현

일정한 길이의 명령어를 가지며 파이프라인을 구현(decode, fetch)


* CISC : 가변길이의 instructions, 실행을 위해 많은 사이클이 걸림


2. Pipelines : 명령어 처리의 속도를 높임


- instructions의 수행은 파이프라인에 의해 병렬로 수행될 수 있는 작은 units으로 쪼개져서 수행 됨

- 이상적인 파이프라인에서는 한 사이클에 각 명령어를 한 단계씩 앞서 처리

- 명령어들은 한 파이프라인 단계에서 decode 될 수 있음

- 마이크로 코드는 필요하지 않음


* CISC는 미니 프로그램에 의해 실행될 명령어인 마이크로 코드가 필요


3. Registers : 데이터 저장을 위한 거대한 레지스터군을 제공


- 빠른 데이터 처리를 위해 로컬 메모리처럼 동작하는 레지스터로 데이터와 주소가 저장


* CISC는 특정 목적을 위한 전용 레지스터를 가짐


4. Load-store architecture 사용


- 메모리와 레지스터사이에 발생하는 데이터 이동에 따른 비용을 줄이기 위해 메모리를 여러번 access하지 않고, 데이터를 여러번 access.

- 데이터 처리 동작과 메모리 access 동작을 분리




### 1.2. ARM 프로세서의 특징


# ARM 프로세서의 고려사항

1. 저전력, 작은 die 사이즈로 설계

2. 제한된 메모리를 고려한 코드 직접도

3. 저가격의 메모리 소자 사용

4. 설계 및 제조비용. 주변장치 공간을 위해 임베디드 프로세서가 차지하는 다이 사이즈 줄이기


# 프로세서나에 하드웨어 디버그 기술 포함

: 신속한 문제해결로 전체적 개발 비용 줄이기


# 순수 RISC의 개념을 벗어남

: 프로세서 자체의 속도보다는 효율적인 시스템 성능과 전력 소모를 중요하게 봄



## 1.2.1. 임베디드 시스템을 위한 명령어 세트


1. 가변 사이클로 실행되는 명령어

: 전력소모, 실리콘 면적, 코드 사이즈를 줄이기 위해 여러 사이클에 실행되는 명령어를 만듬


ex. "multiple load-store"

- 전송될 레지스터의 수에 따라 실행 사이클이 달라지고 메모리에 linear한 access가 이루어짐

- random access 보다 빠르니까 성능 향상


2. 복잡한 명령어 처리를 위한 Inline Barrel Shifter (2장, 3장)

: 명렁어에 의해 사용되기 전, 입력 레지스터 중의 하나를 미리 처리하는 하드웨어 컴포넌트 

: 성능과 코드 집적도 향상


3. 16bit Thumb 명령어

: 코드 직접도 향상


4. 조건부 실행

: 특정 조건의 경우 실행며 분기 명령어의 사용을 줄여주므로 성능 향상 및 코드직접도 향상


5. DSP 확장 명령어

: 기존 DSP와 프로세서가 수행하던 일을 "Digital Signal Process"가 처리

: 16x16비트의 곱셈 처리를 지원하고자 추가



### 1.3. ARM 하드웨어 임베디드 시스템 아키텍처


# ARM 기반 임베디드 하드웨어의 의 4가지 중요 컴포넌트

1. ARM Processors : 임베디드 디바이스 제어. (코어+주변장치 = Memory Management, Caches, ...)

2. Controllers : 시스템의 주요 기능을 담당하는 블록. (Interrupt Controller, Memory Controller, ...)

3. Peripherals : 칩 외부로의 입출력 기능 제공. 메모리 매핑된 레지스터를 통해 주변장치를 제어함

4. Bus : 주변 장치간의 통신 담당



## 1.3.1. ARM 버스 기술

> 칩 내부 버스 사용

> Bus에 연결될 수 있는 디바이스 타입 

- Bus Master : 다른 디바이스로 데이터를 전송할 수 있는 논리 장치 (ARM Processor Core)

- Bus Slave : 버스 마스터로부터 전송 요청이 있는 경우에만 동작 (Peripherals)

> 2-level Bus Architecture 

- 전기적인 특성과 버스폭(16, 32, 64비트)을 담당하는 물리적 단계

- 프로토콜의 처리단계



## 1.3.2. AMBA Bus Protocol

- Advanced Microcontroller Bus Architecture

- 프로세서와 주변 장치를 연결해주는 역할을 담당

- ARM 프로세서의 On-chip Bus Arhcitecture로 채택

- ASB(ARM System Bus), APB(ARM Peripheral BUS)

- AHB(ARM High Performance Bus)

: 하나에 집중된 multiprex bus를 기반으로 빠른 속도를 제공, 64/128bit 폭 지원, 한번에 하나의 버스 마스터를 활성화

- Multi-layter AHB : 동시에 여러개의 버스 마스터를 활성화. 멀티프로세서 시스템에 적합함

- AHB-lite : 기본 AHB 버스의 하위셋으로, 하나의 버스 마스터로 한정시켜 AHB 버스의 특성을 축약시킴

- 다양한 주변장치의 지원을 위한 인터페이스 제공



## 1.3.3. 메모리


# Memory Hierarcy

> Memory의 trade-off : 

- 위치 :  ARM 프로세서 코어 - 캐시 - 메인메모리 - 보조기억장치

- 성능 및 가격 : 캐시 > 메인메모리 > 보조기억장치

- 용량 : 캐시 < 메인메모리 < 보고기억장치


* 대다수의 임베디드 시스템은 캐시의 성능이 불필요함

: 전반적인 성능향상은 도움이 되지만 실시간 시스템 응답에는 도움이 되지 않음


> Memory Width

: 한번에 access 할 수 있는 비트 수. 8, 16, 32, 64 비트

* 32bit ARM 명령어,  16bit width의 메모리 칩에서 캐시가 없는 경우에서는 2번의 Memory Access는 성능의 저하를 가져오지만, 16bit 메모리 값이 상대적으로 저렴


> Types

 ROM(Read Only Memory)

 - 업데이트나 수정이 필요없는 대량 생산품

 - 부트코드 저장을 위해 사용

 Flash ROM

 - 디바이스 펌웨어 저장

 - 전원이 꺼져도 오랫동안 유지해아하는 데이터를 저장

 - Erasing 할 때, 소프트웨어적으로 완전한 제거가 가능하여 가격 절감

 DRAM(Dynamic Random Access Momory) 

 - 디바이스에서 가장 일반적으로 사용

 - storage cell이 데이터를 데이터를 지속적으로 유지하기 위해 수 ms마다 refreshㅏ며 데이터를 지속적으로 충전(refresh는 메모리 사용 전에 DRAM Controller에서 수행)

 SRAM(Static Random Access Momory)

 - 실리콘 공간을 더 많이 필요

 - refresh가 필요하지 않아 "static"이라고 함

 - 캐시와 같은 작은 크기의 high peed task에 사용

 SDRAM(Synchronous Dynamic Random Access Memory)

 - DRAM의 하위 범주에 속함

 - 기존보다 훨씬 더 빠른 클럭속도로 동작

 - 프로세서 버스와 동기화하여 동작

 * "Memory Cells -> Pipeline -> Bus"의 구조로 이동하는 데이터들의 효율적인 처리를 도모



## 1.3.4 Peripherals

- 각 주변장치는 보통 하나의 기능만을 수행. 칩 내에 존재

- 모든 ARM 주변장치는 memory-mapped되어있으며, Controll Register들이 메모리 상에 위치함

- 주변장치를 제어하는 2가지 주요 컨트롤러 : 메모리 컨트롤러, 인터럽트 컨트롤러


# Memory Controller

: 메모리를 프로세서 버스에 연결

- 메모리 디바이스의 사용 가능한 상태를 위한 소프트웨어적인 초기 설정

- 메모리 디바이스는 초기화 코드를 실행

* ex. DRAM : 메모리 타이밍, 리프레시 비율, ...


# Interrupt Controller

: 주변장치나 디바이스가 실행될 때, 프로세서에게 인터럽트를 발생 (인터럽트 발생에 대한 소프트웨어 정책을 제공)

  Interrupt Controller Regitster의 해당 비트를 1로 설정


- Standard Interrupt Controller : 외부 디바이스의 요청에 대한 인터럽트를 프로세서 코어에게 보냄. (요청을 수렴할지 결정)

Interrupt Handler는 Interrupt Controller 내부의 Device Bitmap Regitster를 확인 후 해당 디바이스를 알아냄

- VIC(Vector Interrupt Controller) : 디바이스 혹은 주변장치가 특정시간에 인터럽ㅌ를 발생시켰는지를 결정



### 1.4. Embedded System Software


# Embedded System을 제어하기 위한 4가지 S/W Component


- Initialization Code 

- Operating Systems

- Device Drivers

- Applications


* firmware : 디바이스에 고정되어 있는 ROM code (ex. Initialization code, ...)



## 1.4.1. Initialization Code 

: OS가실행될 수 있는 상태로 만들어 주는 코드.

  OS에게 제어권을 넘기기전 타겟보드(혹은 특정 타켓 그룹)의 동작을 위한 최소한의 부분을 설정


# 초기화코드의 3단계

- initial hardware configuration 

: 초기 하드웨어 설정 코드. 이미지 부팅을 위한 타겟 플랫폼을 설정

(타겟플랫폼의 일반적 설정정, 부팅 이미지의 요구사항에 따른 수정사항, ...)

- diagnostics 

: 진단 코드. 초기화 프로그램에 내장되어 결점을 찾아 수정하는 것을 목표로 함

HW System이 작업 순서에 맞는 처리를 하는지 테스트

표준 시스템 관련 문제 찾기

- booting 

: 부팅 코드. 이미지를 *로드한 후 그 이미지로 제어권을 넘겨주는 작업을 수행

PC를 부팅이미지(OS)의 시작 위치로 옮김

* loading : 코드와 데이터를 포함하여 모든 프로그램과 변수를 포함한 데이터영역을 RAM으로 복사하는 작업

* OS이미지가 압축된 경우 road과정 또는 제어권을 가질 대 압축을 해제함


> Example 1.1.   Memory Layout <

: 메모리 초기화 과정의 필요성

전원공급 시 바로 초기화 코드가 실행되야 함

=> ARM 기반의 임베디드 시스템에서는 일반적으로 Memory remapping을 수행

RAM을 0x00000000 주소로 변경시킴 (Exception Vector Table이 RAM에 존재 하도록 재프로그래밍 될 수 있기 때문임. 2.4절)



## 1.4.2. Operating System 

: 하드웨어 리소스와 infrastructure를 사용하기 위한 일반적인 프로그래밍 환경을 제공

:  OS 환경에서 효율적인 시스템의 사용을 위해 시스템 리소스를 조직 (Memory, Peripheral, ...)


# ARM 프로세서가 지원하는 운영체제의 타입

: ARM 프로세서는 50개가 넘는 OS를 지원. 크게 2가지로 분류


> RTOS : Real Time Operating System. 실시간 운영체제.

이벤트에 대한 반응시간을 보장해야 함. 

반응 시간 초과시엔 성능이 서서히 줄어듬.

일반적으로 보조 저장 장치를 가지지 않음.

- Hard Real-time Applications : 모든 작업에 대한 반응시간을 보장

- Soft Real-time Applications : 충부한 반응 시간을 보장


> Platform OS

규모가 크고 실시간이 필요없는 applications를 관리위해 MMU를 필요로 함

일반적으로 보조기억장치를 가짐 (ex. 리눅스 OS)


> 기타....



## 1.4.3. Applications

: 임베디드 시스템의 특정 작업을 수행


## Device Drivers

: 주변 장치와의 표준 인터페이스를 제공







'System > Embedded' 카테고리의 다른 글

[ARM] ARM 프로세서 개요 2  (0) 2015.11.09
[ARM] ARM 프로세서 개요  (0) 2015.11.09
[ARM] 참고 + ARM 아키텍처의 미래  (0) 2015.11.08
스토리지 시스템  (0) 2015.08.13
컴퓨터 하드웨어  (0) 2015.08.13

### 참고



# ARM 명령어 세트 

(ISA : Instruction Set Architecture)


http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0204ik/Cegbgefe.html


http://www.jkelec.co.kr/img/lecture/arm_arch/arm_arch_4.html#7.1



# ARM7, ARM9 

http://www.jkelec.co.kr/img/lecture/arm_arch/arm_arch_1.html



# 라즈베리파이

https://www.raspberrypi.org/





------------------------------------------------------------------------------------------



ARM System Developer's Guide 

- Designing and Optimizaing System Software





#####

Advanced DSP and SIMD Support in ARMv6

- SIMD Arithmetic Operations

Future Technologies Beyond ARMv6

- TrustZone






### 15.1. ARMv6 에서의 DSP 및 SIMD 명령어



## 15.1.1. SIMD 산술 연산





### 15.4. 향후 새로운 기술



## 15.4.1. TrustZone

'System > Embedded' 카테고리의 다른 글

[ARM] ARM 프로세서 개요 2  (0) 2015.11.09
[ARM] ARM 프로세서 개요  (0) 2015.11.09
[ARM] ARM 임베디드 시스템  (0) 2015.11.08
스토리지 시스템  (0) 2015.08.13
컴퓨터 하드웨어  (0) 2015.08.13

# S5FS

- System V File System 

- 하나의 볼륨(하나의 disk drive, 하나의 partition)당 하나의 파일시스템을 갖음

- 하나의 파일시스템은 Stand alone 시스템 : 파일에 대한 모든 컨텐츠와 정보들이 하나의 볼륨안에 저장이 됨

-  하나의 partition에 존재하는 block의 크기는 512 bytes (512, 1024, 2048)

- Sector들의 linear array = block의 linear array

- Boot Area : 0번째 block에 위치하며, Boot Program을 저장하고 있음.

Boot Area에서 Boot Program을 메모리로 로드하여 하드웨어 디바이스를 부팅시킴

- Super Block : 볼륨에 대한 파일시스템의 모든 메타데이터.

- inode list 


=> 전통적인 초창기 모델이므로 성능과 안정상에 문제를 가지고 있음

- 파일의 inode와 data block간의 물리적인 거리가 멀기 때문에 파일에 접근 시 과도한 Seek Operation이 발생

- Data Block의 할당/해제를 반복할수록 free block이 산재하게 되어 sequential block을 읽을 때 과도한 Seek Operation이 발생

- super block이 한곳에만 저장되어 있으므로 손상될 경우 파일시스템을 사용할 수 없음

- 컴퓨터 시스템에서 빈번하게 사용하는 operation에 최적화 되어있지 않음. 중구난방으로 흩어져 있음



# FFS

- UFS : Unix File System

- self-contained file system

-  cylinder group이라는 개념을 도입

: 인접한 cylinder를 묶어서 그룹화, 지역적으로 비슷한 곳에 있는 정보는 같은 cylinder group에 저장

- cylinder group마다 super block을 가짐(super block을 여러개 두어 recoverry를 도모)

- block안에 fragment라는 더 작은 단위를 도입. fragment단위로 allocation

- 하나의 cylinder group에 저장하기 힘든 사이즈가 큰 파일들은 인전 cylinder group으로 넘어감. (48KB 이상이 되면)


<장점>

- seek optimization.  적절한 spreading으로 동일한 파일의 Block들이 멀리 떨어져 저장되는 것을 방지

- lotational Delay optimization.

: seek operation에서 sector를 읽으려면 disk driver에서 read request 만들어서 날려야 할 때, 2 sector가 지나가는 시간이 걸린다고 가정.

0번 sector를 읽고 1번 sector를 읽어야 할 때, 한번 resquest를 하면 2개의 sector가 지나가면 1번 sector를 읽기위해서는 다시 한바퀴를 돌아야 함.

=> 이런 문제를 방지하기 위해 lotational delay를 계산하여 sector에 저장하도록 함

- long file name의 지원. 256characters.

- symbolic links의 도입

- Disk quota 도입


<한계>

- sequential read의 한계

- crash recovery가 느려지는 문제 발생. disk storage의 block size가 굉장히 빠르게 증가. 

=> 적절한 부팅 시스템을 무시하고 시스템을 power off하면 rebooting할 때 파일시스템의 inconsistency를 확인.

=> "fsck", file system check라는 command를 수행하는데 굉장한 시간이 걸림

=> log structured file system을 사용하게 됨


# LFS

: Log-structured File System 


> Crash recovery의 필요

- 성능향상을 위해 inode cache를 가지는 구조에서 문제가 발생하면 disk의 inode의 값과 메모리의 inode값이 일치하지 않게 될 수 있음

- disk에 대한 operation은 transaction과 같아 synchronous write를 수행하게 됨 


> fsck의 수행동작

- 시스템에 존재하는 inode들을 체크하여 used block들을 확인

- used block들의 구조에서 각각의 directory 별로 file contents를 모두 확인하여 파일의 inode를 확인

- inode indexdp mapping된 데이터가 제대로 있는지 확인. 찾을수 없는 파일이나 연결이 안된 디렉토리들... 

- lost + found directory에 보내기


> LFS 구현

- 새로 생성될, 새로 추가될 정보만 파일의 정보 뒤에 붙이게 됨

- log : Operations나 values, redo/undo log, 

- garbage collection : 어느 시점이 되어서 로그가 너무 방대해지면 sequential read operation이 굉장히 느려지게 됨

- group commit

- retrieval


# Disk Scheduling

- Request Queue : disk에 대한 I/O request를 저장하는 queue

- device drivers와 devices 사이에 request Queue가 위치

device driver에 I/O Scheduler가 스케쥴링을 수행

- Request Ordering을 수행하여 시간을 줄임

FIFO/FCFS (x)

SSTF (x)

Scan like Elevator (x)    => 양방향에 위치한 애들만 너무 불리해

Circular Scan (o)


> Flash memory 등의 경우에는 disk보다 더 복잡한 스케쥴링이 필요하게 됨

: bus share, multi processor, 공정의 여러 제약 등 






 

'System > Etc.' 카테고리의 다른 글

git  (0) 2016.01.17
FDT  (0) 2015.11.14
[OS 기초] File System  (0) 2015.11.05
[OS 기초] I/O Device와 Device Driver  (0) 2015.11.05
[OS 기초] Demand paging 3 - Trashing, Working Set  (0) 2015.11.04

# Files and Directories

# File System

# File Structures

# Disk Space Management

# Unix File System

# Disk Scheduling

# Conclusion



# File 

: 이름을 가지는 디스크에 저장되는 바이트의 집합


> Views 

- OS가 보는 File : Block Sequence. Disk는 Block Storage 이므로 Block 단위로 저장 (내부)

- User가 보는 File : Bytes Sequence  (외부)

=> OS의 File System은 User가 보는Bytes 단위를 시스템 OS가 보는 Block 단위로 mapping 해야 함


* Naming 

: Disk 상에 존재하는 File은 addressing할 수 있어야 하는 이유로 인해 외부적으로는 Text Name을 가져야 함. 내부적으로는 File Identify를 가져야 함.

(*OS는 Naming을 File 뿐만아니라 I/O Devices 에도 적용시킴)


* File Descriptors 

: 파일의 내용에 접근하기 위해 필요한 메타데이터들을 저장하는 자료구조. 


* Operations on Files

- create and delete files

- open files for reading and writing 

- seek within a file

- read from and write to a file

- close files 

- create directories to hold groups of files

- List the contents of a directory

- Removes files from a directory


# File Descriptors

- unix에서는 index node라고도 부름

- 파일의 메타데이터를 저장하는 자료구조

- 파일의 크기, 소유자, 소유 그룹, 액세스 타임, 접근 권한, ...

- inode : unix의 file system에서 파일에 대한 메타데이터를 저장하는 자료구조

- i-node의 index :  i-number, file descriptor의 ID. 


> FIle Descriptors의  저장

과거: array의 형태로 만들어 disk에 특정 block을 할당하여 저장.    

=> 과거 disk는 bad block이 많고 취약했기 때문에, single copy로는 데이터 보호를 제대로 할 수 없음

=> File Descriptor들을 디스크의 특정 영역에 모아두면 성능저하가 발생

: 디스크 스토리지 상에서 File Contents와 File Descriptors를 나누면 물리적인 거리가 멀기때문에 Seek Time이 커짐

현재 : data contents 근처로 file descriptors를 가까이 두어 분산시키거나, data recovery를 위해 data의 copies를 여러개로 만듬


-  in memory cache : 성능의 향상을 위해 File Descriptor의 복사본을 Main memory에 유지

=> 부작용이 생길 수 있음. File Desciptor의 값을 수정할 때, Disk와 Main Memory에저장된 File Descriptor의 값이 달라질 수 있음


- 과거, Main Memory의 Cache에 복사한 file descriptor의 값을 안전하게 Disk에 옮기지 않고 시스템을 종료하면,
    시스템 재부팅 시에 OS는 해당 내용을 Disk의 file descriptor의 내용을 재구성해야함.

but,  현재는 디스크의 용량이 굉장히 커져 복구하기가 어렵고, 재부팅이 시스템을 정상화 하게 하는 경우가 많아짐(스마트 폰...)

=> log structured file system으로 진화


# Directories

- bytes sequence

- File 및 sub directories를 가지고있는 entity

- 내부적으로 File과 동일하게 관리

- File과는 다르게 data content로 contains(text file name, descriptor index) 값을 가짐. 

=> file의 text name을 file id로 mapping하기 위한 기본 데이터


> Unix File System의 구조

- tree 구조

- root directory, 하위 디렉토리는 각 leaf가 root로 부터 unique

- root directory의 inode number : 2

* why? http://stackoverflow.com/questions/12768371/why-root-directory-is-always-stored-in-inode-number-two

- name parsing 


# 부가사항

> Working Directory : 현재 위치한 디렉터리

> Link : 선택적으로 필요에따라 back-door path를 지정하는 기능


* inode의 i-number 값은 system wide하게, unique 하게 부여하는 것이 아니라, 볼륨 단위로 부여를 함


- Symbolic Link : 링크시킬 파일의 full path 값을 새로 링크시켜줄 디렉터리에 복사

원본 파일 A에 대해 심볼릭 링크를 생성하면, A라는 가리키는 파일을 생성

( "symbolic_link_file_B -> original_file_A" )

원본파일 A를 삭제하면 A를 가리키던 심볼릭링크파일도 삭제 됨됨(수정도 마찬가지)


- Hard Link : 링크시킬 파일의 contains pair 값을 새로 링크시켜줄 디렉토리에 그대로 복사. 

원본 파일 A에 대해 하드링크를 생성하면, A라는 파일을 가리키는 "이름"을 하나 더 만듬.

즉, 둘 중 하나의 파일을 삭제하더라도 이름 뿐인 녀석을 삭제하였으므로 내용은 그래도 남게 됨. 한 녀석은 그대로 존재하게 됨


=> symbolic link가 더 유연함. i-node의 number는 볼륨 단위로만 unique 하므로 Hard Link에 사용하는 contains pair값은 system wide하게 unique하지 않음.

즉, Hard Link는 같은 볼륨내에서만 사용이 가능

=> symbolic Link는 full path를 가지고 구현하기 때문에 모든 link는 system wide하게 unique 함

즉, 다른 볼륨간에도 사용할 수 있음


# Big Picture

> File System 기능

1. logical file name(logical resource name)을 physical address로 변환하기 위해 naming 기능을 제공

2. 사용자의 데이터를 저장장치로부터 read/write 하는 기능을 제공


> Views on Files

- User

file name + byte offset

: file pointer로 offset을 움직이며 파일 읽기

* file 단위의 sequence of bytes

* 주요 file access 패턴

- sequention access : file pointer를 한 칸씩(bytes) 움직이면서 파일의 내용을 읽기

- random access : file pointer를 임의로 이동하면서 파일의 내용을 읽기


- Kernel 

ino + logical block number

* file안에 존재하는 sequence of block

* bytes단위가 아닌 block 단위로 내용을 읽기

* kernel의 file system은 밑에 device driver와 interface 해야 함

* file descriptor, = index node


- Device Driver

Physical block number

* disk volume 단위로 관리, sector들의 linear sequence

* volume : 단일 file system으로 관리되는 저장 장치 상의 영역

* sector들의 number


- Device

cylinder number

head number

sector number

drive number 이미 minor number로 사용 중


> File System in the Kernel (linux case)


user space            : file I/O    (system call : create, read, write, open, I/O contol)

--------------------------------------------------------------------------------

kernel space         : Virtual File System (VFS)  -> individual한 파일 시스템을 유니폼하게 사용자에게 제공하기 위해 필요


Individual Filesystems(EXT3, EXT4, JFFS2, VFAT, ...)


Buffer Cache(Page Cache) -> 최근 접근한 file의 Data Block의 내용을 Main Memory에 저장해 두는 공간으로 

디스크로 부터 한번 읽어온 파일의 내용에 다시 접근할 때, 빠른 속도를 제공함

(buffer cache도 swapping함. LRU같은 Policy를 적용)


I/O Schedulers


*Request Queue / Response Queue


Block Drivers   ,     Block Driver(FTL)

--------------------------------------------------------------------------------

Storage Media     : Disk ...... Flash



# File Structures

- Sequential access. ex. 방대한 코드를 컴파일 할 때,

- Random access.  ex. 데이터베이스에서 특정 데이터를 읽을 때, demanding paging에서 특정 page를 읽을 때, 

- keyed access. ex. 특정 key로 데이터를 읽을 때, (OS에서는 처리하지 않음)


* 과거 디스크는 fragmentation의 문제가 있음

=>  비연속적인 block단위로 allcation을 수행하여 fragmentation의 문제를 해결


1. Linked File 구조

: 해당 파일 디스크리터에 기록된 파일의 첫번째 블록의 주소를 통하여 파일에 접근

: fragmentation의 문제는 해결

: sequential access는 문제가 없으나, random access의 경우에는 seek time이 굉장히 오래 걸리게 됨

: 1970년대..


2. Indexed File 구조

: Unix의 기본 file 구조

: file descriptor에 파일이 가지고있는 block들에 대한 포인터를 index array로 저장

sequential access, random access 둘다 용이함

: data block들은 file system의 sector array 중 임의의 block을 할당. 각 file의 file descriptor들이 해당 block들을 가리키는 구조

: file descriptor는 일정한 크기를 갖는 descriptor들의 array로 구성. 

=> 그안에 넣을수 있는 index의 갯수가 제한. 한 파일의 크기는 index의 갯수만큼 제한된다는 단점!

=> double indirect block 구조를 사용하여 큰 사이즈의 파일도 수용할 수 있음

 (but, 이중으로 처리하는 이러한 구조는 기존에 비해 데이터를 더 액세스해야하므로 seek time이 증가)


# Related Mechanisms

1. Block buffer cache

2. bit map operation  : 디스크 블락을 할당할 때, 꼭 sequential한 위치에 할당하지 않아도 되지만, seek time을 줄이기 위해 같은 실린더안에 있는 block을 할당하거나 하는 등의 인접한 위치의 block을 할당하는 방법

=>  OS의 File System에선 비어있는 연속된 block의 위치를 bit map을 통해서 알 수 있음

=> block들에게 1bit씩을 할당하여 1이면 이미 할당됨을, 0이면 할당되지 않고 비어있음을 나타내게 함함

=> 소프트웨어적으로도 구현이 가능하나 대부분의 마이크로 프로세서가 해당 기능을 제공


* Bit Map을 사용한 디스크의 free block 관리

: 각 bit가 디스크의 block이 사용 중인지 아닌지를 나타내는 Array. 

 HW/SW String Search 기법을 사용해 연속적인 사용 가능한 block을 쉽게 찾을 수 있음


> File의 구조를 결정하는 요소

: sequention access, random access를 효율적으로 지원해야함

작은 file, 큰 file 모두 효율적으로 지원해야 함


> must have items

1. Naming

2. Protection

3. Reliability

4. Disk Space Management 


# Disk Space Management

: File이 생성되거나 확장될 때, 어떻게 disk sector들을 file에 할당해 줄것인가를 결정

- 오버헤드가 적게

- 파일에 빠른 액세스가 가능하게 등등

- 파일의 각 block들

- matadata : user에게는 보이지는 않지만 커널이 각 파일별로 관리. 

in-memory cache를 유지하고, system이 shutdown될 때는 consistency를 잘 유지해야 함

- crash policies


> Disk space allocation policies

1. contiguous allocation

2. Block-based allocation

3. Extent-based allocation : block들을 그룹으로 묶고 각 그룹에 semantics를 부여함으로써 최적화를 달성하는 정책

=> block 단위로 allocation을 하면 sequential read를 할 때 seek가 많이 발생하므로 큰 단위로 할당해야하는 필요가 있음



# Unix File Systems

- System V file system : s5fs

: 완전 기본적 전통적인 파일시스템

- Berkeley fast file system (FFS) - often called UFS, 1980 년대 s5fs를 개선

- Sun's network file system (NFS) - 분산 operation과 file system을 접목

- Sun's virtual file system (VFS) - 다양한 파일시스템을 지원하기 위한

- Log-structured file system (LFS) 






 

# I/O Hardware

# Device Drivers

# Colision



# I/O Hardware

CPU, Memory, HardDisk, Network card, ...


<Bus>

- System Bus, I/O Bus, 

- Address Bus, Data Bus, Control Bus 

- ISA, PCI, EISA, SCSI ...


> I/O Device 

- Controller, logic

- Register set


> I/O Device 내부의 Registers

- Status Register : 장치의 상태를 보여주는 Register

- Control Register : 장치의 동작을 결정하는 Register

- Data Register : 입출력할 데이터를 잠시 보관하는 Register

- Instruction Register ...


> I/O Device의 Register에 접근하는 두가지 방법

- Memory-Mapped I/O : 별도의 I/O address space를 갖지 않고, Physical address space의 일부를 할당하여 사용

* register를 access 하기위해 load/store 명령어를 사용 (모토롤라...),

- Port-Mapped I/O : 메모리의 주소와는 다른 방식의 주소를 할당하여 사용

* register를 access 하기위해 in/out 명령어를 사용 (Intel processor...), 


> Device Control

- device control = device의 register들을 프로그래밍

- OS는 I/O Bus의 address line에 특정 register의 address를 보낸 후 read/write같은 명령을 보내 수행하게 함


# I/O Devices의 분류

: unix OS는 굉장히 단순화 시키려고 노력하였으며 이런 환경에서 I/O Devices를 특성에따라 모델을 나누게 됨


- Character Devices : 입출력을 Character 단위로 수행. mouse, terminal, ...

- Block Devices : 입출력을 block이라는 임의의 단위로 수행. Disk Drive, Flash Drive, ...

- Network Devices : NIC, ...


> Character Devies


* ex. 


<Mouse driver의 역할 요약>

- Mouse Interrupt 발생 시, Mouse의 Data Register에서 값을 읽어오는 역할

- interrupt를 Event로 바꾸어 주는 역할


<Keyboard Driver의 역할>

- 키보드로부터 들오오는 각 캐릭터들을 Line buffer에게 순서대로 저장

- End-of-Line Character가 들어오면 전체 Line Buffer에 있는 데이터를  OS에게 전달


> Block Devices

- spindle

- arm assembly, arm, read-write head

- Track : 한 디스크 표면에서 스핀들로부터의 거리가 동일한 환형의 저장 공간

- cylinder : 여러장의 디스크를 수직으로 쌓여있는 동일한 반지름의 Track들의 집합

* cylinder 단위의 데이터 접근이 중요한 이유 (왜 cylinder라는 개념이 있는건가?)

: Arm Assembly가 고정된 상태에서 여러 platter에 걸쳐있는 한, 실린더의 트랙들을 동시에 읽을 수 있기 때문

- sector : 각각의 track을 분할하는 디스크 read/write 단위의 영역


> Disk Operation


* Sector : 디스크를 읽을 때 data transfer가 일어나는 최소 unit.

Sector에 접근하기 : cylinder number, track number in the cylinder, sector number in the cylinder


1. read/write head 선택

2. "seek", arm assembly를 해당 cylinder로 이동. (Move heads to the correct track)

* seek time : arm을 목표한 지점(해당 cyliner)까지 이동하는데 걸리는 시간

3. 해당 sector가 돌아올때까지 기다림 (spindle의 회전수에 비례, RPM-Rotation Per Minute)

* Rotational Delay : 디스크가 회전하여 목표한 지점(해당 섹터)이 head에 도착하는 시간


> Disk Performance

- seek time : 0-50 ms (avg 10-20 ms)

- rotational delay : 0-16ms

- typical drive spins at 3600-5400 RPM



> Flash Drive

- NAND flash memory : RAM과 Access pattern이 굉장히 다름. data tranper가 bytes단위가 아닌 block 단위로 일어남

- Page : Read/Write를 수행할 때 대상이되는 Data block. 2KB, 4KB, 8KB

* Page의 일부분은 Data를 저장하는 공간과 Spare Area라는 패리티, 에러처리 등 부수적인 정보 등을 저장하는 공간으로 나뉨

- Block : 64 pages, 128 pages


* Flash Memory > Blocks in a Flash Memory > pages in a Block > Spare areas in a page


* Flash Operations

- read : 하나의 페이지를 통째로 읽어옴

- write/program : flash의 해당 영역을 굽기

- erase : block 지우기. flash는 rom이므로 rewrite할 수 없음. 우선 지우고 다시 써야함.


<특성, 제약사항>

* Erase-before-write : NAND Flash 메모리는 데이터의 덮어쓰기가 불가능 하기 때문에 먼저 Erase로 초기화 한 후 write 해야 함.

* Worn-out : Erase 가능한 횟수가 제한적임

* Wear-leveling : NAND Flash의 한 영역에 Erase가 집중되어 worn-out이 발생하는 것을 막기위해 전체 영역을 고루 사용하도록 조절하는 기술

* read/write의 단위는 page, erase의 단위는  block


- Flash Memory를 Storage로 사용해 file system 구성하려면, Erase-before-write라는 제약조건 때문에 

반드시 Log Structure Architecture가 필요함


> Page단위로 write를 수행하다가 Erase를 수행할 때, 단위가 block으로 page보다 크므로 지우려는 page 외에도 다른 page의 데이터가 모두 지워짐

> 로그를 남겨 관리를 해야함. page remapping after update.

=> Log-structured file system


# Device Drivers

:  I/O Devices의 Control다른 프로그램들이 어떤 하드웨어 디바이스를 잘 사용할 수 있게 컨트롤 해주는 컴퓨터 프로그램

- 하드웨어 적인 측면을 관리하며, 기능을 사용자에게 추상화 시켜 사용하기 편하게 도와주는 역할을 함

Application과 Device, OS와 Device  사이에 위치하며, User들이 Device를 사용하기위해 함수들을 제공


* SW System의 구성

- 정적인 구성요소 : structure(process)

- 동적인 구성요소 : behavior(program)


- Device Drives의 요소

정적 구성요소 : Device Drives를 User Program이 사용하기 위해 호출하는 APIs, Operations...

동적 구성요소 : Interrupt Service Routin. 

=> 즉, Device Drives는 라이브러리이며 어떤 구성요소는 Interrupt에 의해 호출되며, 어떤 구성요소는 User Programs에 의해 호출됨


- UNIX 계열의 Device Drivers


* Unix 

- 시스템의 단순화, portability 높이기.

portability를 높이기
 : machine dependent 
한 부분을 정형화 시켜서 정리해야 함

 : micro processor에 micro architecture specipy한 부분(MMU, context)이나, Memory layout, system bus architecture, Device관련 부분 들


* Unix Device Drivers의 대표적인 5가지 함수

- Open : 디바이스를 initialization. OS관점에서 레지스터와 디바이스 드라이버가 필요한 데이터 스트럭쳐를 잡아주는 역할 등

- Close : release

- read/write

- I/O CTL : I/O Contol


* Type of Unix/Linux Device

- Character Devices : data transfer unit이 캐릭터 단위. 시퀀셜 엑세스에 사용

일반적으로 사람과 상호작용 하므로 보통 slow device.

- Block Devices : 데이터 트랜스퍼 유닛이 블럭단위. 랜덤 엑세스에 사용

* block buffer cache : Large scale의 볼륨을 단위로 high speed가 필요함. 캐시로 CPU에 비해 상대적으로 속도가 느린 block device의 성능을 보완한 것.

- Network Devices


> File System의 역할

1. 디스크에에 있는 데이터를 읽거나 쓸 쑤 있는 여러 기능을 제공

2. File이나 Device 같은 시스템에 존재하는 자원에게 Name Space(simbolic name)를 제공(Unix/Linux에서는 path와 같은 형태..)


> Device File : 일종의 스페셜 파일을 생성하여 파일과 디바이스를 연결시키기

- 일반 데이터 파일로 관리

- /dev 밑에 file의 형태로 존재

- 하나의 디바이스에 여러 이름의 파일을 붙일 수 있음

ex. /dev/psaux, /deb/psmouse = serial mouse


* File의 데이터

- Real Data

- Metadata : file의 특성을 표현하는 부가적인 데이터

: 생성일, 수정일, 엑세스 권한 등


- Device File의 metadata

- Device Type : block, charactor

- Major Number : 어떤 타입의 디바이스인지 나타내는 필드. tty, 

- Minor Number : 대상이 되는 디바이스를 구별하기 위해 디바이스 드라이버에게로 보내는 argument. (Kernel don't care)





+ Recent posts