반응형
RISC-V
RISC-V는 오픈 소스 명령어 집합 구조(ISA, Instruction Set Architecture)입니다.
RISC-V는 Reduced Instruction Set Computer (RISC) 원칙에 기반을 두고 있으며, 주로 다음과 같은 특징을 갖고 있습니다:
- 오픈 소스 및 무료: RISC-V의 가장 큰 특징은 오픈 소스이자 무료로 사용할 수 있다는 점입니다. 이는 누구나 RISC-V 명령어 집합을 사용하여 자유롭게 하드웨어를 설계하고 구현할 수 있다는 것을 의미합니다.
- 모듈식 설계: RISC-V는 기본 명령어 집합과 여러 확장 명령어 집합으로 구성된 모듈식 설계를 채택하고 있습니다. 이는 사용자가 특정 응용 프로그램에 필요한 명령어만을 선택하여 사용할 수 있게 하여 설계의 유연성을 높입니다.
- 단순함과 효율성: RISC-V는 단순하고 효율적인 설계를 목표로 합니다. 이는 설계와 구현을 단순화하여 하드웨어의 성능과 에너지 효율성을 높이는 데 기여합니다.
- 확장 가능성: RISC-V는 32비트, 64비트, 그리고 128비트 주소 공간을 지원하며, 다양한 응용 분야에 맞추어 쉽게 확장할 수 있습니다.
- 광범위한 응용 분야: RISC-V는 임베디드 시스템, 데스크톱 컴퓨터, 서버, 슈퍼컴퓨터 등 다양한 응용 분야에 사용할 수 있습니다. 특히, IoT(사물인터넷) 장치에서부터 고성능 컴퓨팅에 이르기까지 다양한 용도로 활용될 수 있습니다.
- 활발한 커뮤니티 및 생태계: RISC-V는 전 세계적으로 많은 기업, 연구 기관, 개발자들로 구성된 활발한 커뮤니티를 가지고 있습니다. 이는 지속적인 발전과 생태계 확장을 가능하게 합니다.
RISC-V Registers
- 32bit (0x0 ~ 0x31)
RISC-V: Structure of ISA
- 소량의 고정식 레지스터 입니다.
- RV32I의 경우 32비트 레지스터 32개로 구성되어 있습니다. (RV64I의 경우 64비트 레지스터 32개)
- 레지스터의 숫자는 크지 않은 이뉴는 무엇일까요? (1024개의 레지스터가 아닌 이유는 무엇입니까?)
Why? Register의 개수가 많이지면? Register를 찾는데 오래 걸림 (Cycle 소요시간 상승 & 성능 저하 + 저장공간 issue)
- 32 = 2^55 비트 레지스터 지정자는 RISC의 3-address에 충분합니다 (만약 opcode라면 경우는 어떨까요>)
- 레지스터의 수 ↑; 신호 거리 ↑; clock cycle ↑
if. Register가 1024면? 32bit인데 10bit x 3, OP Code는 2bit. → 즉, 연산 4개 까지만 가능..
3종류의 Instruction Set
연산 : 레지스터 ↔ 레지스터
- 로드/저장: 메모리와 레지스터 파일 사이 데이터를 이동시킵니다.
- 제어 흐름: 코드의 다른 부분으로 점프합니다.
A RISC-V Example (”00A9 8933”)
32bit → 4 byte
- 이 4바이트 이진값은 RISC-VCPU가 수행하도록 지시합니다.
- 레지스터 x19 x10에 값을 추가하고 x18에 저장합니다.
- 프로세서 속도, 내부 구현 또는 칩 설계자에 관계없이 수행합니다.
명령어의 4 byte 에는 arg1, arg2, arg3, op를 입력해야 합니다.
Aside: CISC and x86
X86 ISA is CISC(“Complex”)
- C3
- Mnemonics: ret
- Description: 함수 종료(return)를 의미하는 명령어입니다.
- 48 b8 88 77 66 55 44 33 22 11
- Mnemonics: movabs rax, 0x1122334455667788
- Description: rax 레지스터에 64비트 상수 값 0x1122334455667788을 이동하는 명령어입니다.
- 44 33 22 11
- Mnemonics: (이 부분의 해석이 이미지에서는 누락된 것 같습니다. 하지만, 아래 명령어에 포함된 것으로 보입니다)
- 64 ff 03
- Mnemonics: DWORD PTR fs:[ebx]
- Description: fs 세그먼트 레지스터를 이용해 ebx 레지스터가 가리키는 메모리 위치의 32비트 값을 사용합니다.
- 64 67 66 f0 ff 07
- Mnemonics: lock inc WORD PTR fs:[bx]
- Description: fs 세그먼트에서 bx 레지스터가 가리키는 메모리 위치의 16비트 값을 원자적으로 증가시키는 명령어입니다. lock 프리픽스를 사용하여 여러 프로세서 간의 동기화를 보장합니다.
- 2e c4 e2 71 96 84
- Mnemonics: vfmaddsub132ps xmm0, xmm1, xmmword ptr cs:[esi + edi * 4 + 0x11223344]
- Description: xmm0와 xmm1 레지스터의 값과 메모리 위치 cs:[esi + edi * 4 + 0x11223344]의 128비트 값을 사용하여 부동 소수점 곱셈 및 덧셈/뺄셈을 수행하는 명령어입니다.
RISC-V Instrucion Encoding
제한사항 → 형식 고정
- 32비트 명령어로 인코딩 됩니다.
- 작업 코드(opcode), 주소 지정 모드, 피연산자,... → 물리, 분기 연선을 지원합니다.
- 명령에 따라 매개 변수가 다릅니다(register, emptiates, ...) → 다양한 연산자를 지원합니다.
- 다양한 필드를 일관된 위치로 인코딩해야 합니다. 더 단순한 디코딩 회로로 진행해야 합니다.
- Answer: RISC-V는 6개의 "유형" 명령어 인코딩을 사용합니다 → 다만 형식 수가 적습니다.
- 7bits (opcode): 위치가 고정되어 있습니다. → 7bit만 읽으면 어떠한 연산을 해야 하는지 이해 가능.
- R-type: add, sub, and, or (opcode: 51) src: rs2, rs1, dst: rd
- I-type: load(opcode:3); base : rs1 offset : immediate rd = base + immediate
- S-type: store(opcode:35); base : rs1 offset : immediate rs2 = base + immediate
- SB-type: beq(opcode:99);
RISC-V Instruction Type: R-Format
- 필드에는 이름이 있습니다
- 각 파일은 서명되지 않은 unsigned int(크기) 로 표시됩니다
- 5비트: 0-31 / 7비트: 0-128
- opcode: partially 지정 연산
- Ex. R-type opcode: 0b0110011 / SB-type opcode = 0b1100011
- func7+ func3: opcode가 있는 부분 combined, 어떤 연산을 수행하는지 describe(묘사)
- R-type 명령어는 몇 개입니까? 27 + 23 = 2^10
- rs1: 1st operand(피연산자) (소스 레지스터)
- rs2: 2nd operand(피연산자) (2차 소스 레지스터)
- rd: destination (대상 레지스터)
R-Format Example) add x5, x6, x7
x6(00110, x7(00111) 레지스터의 값을 더한 결과를 x5 레지스터(00101)에 저장합니다.
- Combination of fun3 and fun7
RISC-V Instruction Type: I-Format
- 즉시 사용할 수 있는 명령어는 무엇입니까?
- 5비트 필드가 너무 작아서 가장 즉시 사용할 수 없습니다
- RISC-V는 (단순화를 위해) 단 하나의 명령 형식만 가질 수 있습니다.
- 안타깝게도 여기서는 타협해야 합니다.
- R-형식과 대부분 일치하는 새 명령어 형식을 정의해야 함
- 우리는 즉시 피연산자로 사용하기 때문에 소스 레지스터 1개와 목적지 레지스터 1개가 필요합니다
- 필드의 합은 32비트입니다.
- imm field의 R타입과 다릅니다.
- Opcode(7비트): 명령어의 종류를 나타냅니다.
- Ex. R-type opcode: 0b0110011 / SB-type opcode = 0b1100011
- rs1(5비트): 첫 번째 소스 레지스터를 나타냅니다 (에시에서는 x1)
- rd(5비트): 결과를 저장할 대상 레지스터를 나타냅니다. (이 예에서는 x15)
- funct3(3비트): 명령어 내에서 세부 연산 유형을 정의합니다.
- imm: 12bit 수
- 모든 계산은 32bit 워드로 수행되므로 32bit로 확장해야 합니다(Always sign-extended)
- 2^12 즉시 표현 가능 → [-2^11, +2^12]
I-Format Example) addi x15, x1, -50
x15는 연산 결과를 저장할 대상 레지스터, x1은 연산에 사용할 원본 레지스터, -50은 x1 레지스터의 값에 더해질 즉시값입니다.
- "imm [11:0] 111111001110"은 RISC-V 명령어에서 사용되는 12비트의 즉시 값(immediate value)을 나타냅니다.
- 이 이진수 값 "111111001110"은 2의 보수 방식으로 표현된 -50을 의미합니다.
- RISC-V에서 즉시 값은 보통 연산에 상수 값을 직접 사용하기 위해 포함되며, 여기서는 레지스터에 -50을 더하거나 빼는 등의 연산에 사용될 수 있습니다.
2의 보수 표현에서 음수를 원래의 값으로 변환하기 위해서는 전체 비트를 반전시킨 후 1을 더해주면 됩니다.
따라서 "111111001110"의 반전 값은 "000000110001"이 되고, 여기에 1을 더하면 "000000110010"이 됩니다. 이를 십진수로 변환하면 50입니다. 따라서, 원래의 이진수 "111111001110"은 -50을 나타냅니다.
srli vs. srai
shift right logical (immediate) vs. shift right (arithmetic)
srl 명령어 (I-type 포맷): 0000000 shamt rs1 101 rd 0010011
srai 명령어 (I-type 포맷): 0100000 shamt rs1 101 rd 0010011
- 적용 예시로, 레지스터 x5의 값을 2비트 우측으로 논리 이동하려면, srl 명령어를 사용하고 shamt를 00010으로 설정합니다.
- 산술 이동의 경우 srai 명령어를 사용하고 동일하게 shamt를 설정합니다.
- 논리 우측 이동(Logical Right Shift, srl)
- 이 명령어는 주어진 비트 수만큼 레지스터의 값을 우측으로 이동시키며, 왼쪽에서 새로 들어오는 비트에는 0을 채웁니다.
- 논리 우측 이동은 부호 비트를 보존하지 않으므로, 주로 부호 없는 데이터를 처리할 때 사용됩니다.
- 산술 우측 이동(Arithmetic Right Shift, srai)
- 이 명령어도 주어진 비트 수만큼 레지스터의 값을 우측으로 이동시키지만, 산술 우측 이동은 부호 비트(sign bit)를 보존합니다.
- 즉, 이동 후 왼쪽에서 새로 들어오는 비트는 원래 레지스터의 가장 왼쪽 비트(부호 비트)의 값으로 채워집니다.
- 이런 특성 때문에 산술 우측 이동은 주로 부호 있는 데이터를 처리할 때 사용됩니다.
Load instruction
- 메모리에서 레지스터로 데이터 로드합니다.
- (rs1)의 기본 레지스터에 12비트 부호를 즉시 추가하여 메모리 주소를 형성합니다.
- 메모리에서 로드된 값이 rd에 저장됩니다
I-Format Example) addi x15, x2, -50 ??
RISC-V Instruction Type: S-Format
- 저장소에 두 개의 레지스터 –rs1: base address / rs2:저장할 데이터와 즉시 오프셋이 필요합니다
- 다른 명령어와 같이 rs2와 즉시 샘플을 둘 수 없습니다.
- rd는 필요 없습니다.
설계원리
- rs1 / rs2 파일을 같은 장소에 보관합니다.
- rd 파일이 있던 곳으로 낮은 5비트를 다른 instruction으로 이동합니다.
S-Format Example) sw x14, 8(x2)
- x14, x2 → Base address
- word 단위로 store → like x2 register + 8 offset
sw x14, 8(x2) 명령어에서 imm [11:5]가 7비트 크기의 즉시값 → 즉시값은 0
- sw x14, 8(x2)는 x2 레지스터의 값에 8을 더하여 계산된 메모리 주소에 x14 레지스터의 값을 저장하는 명령어입니다.
- x14 레지스터의 값은 메모리 주소 x2 + 8에 저장됩니다.
- 12 bit offset은 imm [11:5](7비트) 와 imm [4:0](5비트) 를 결합하여 12비트의 즉시값을 구성합니다.
RISC-V Instruction Type: SB-Format
- Branch Instructions
- beq, bne, bge, blt
- Branch(점프)할 주소를 지정해야 합니다.
- 또한 비교할 레지스터 2개를 가져갑니다 (조건)
- 그리고 등록할 register을 쓰지 않음
- 그러면 라벨을 어떻게 인코딩할까요?
- PC-상대 주소를 지정하는 방식으로 진행합니다.
- SB-Format 일반적으로 루프에 사용되는 분기 명령어 입니다 (다른 경우에는 잠시)
- if-else, for, while
- 루프는 일반적으로 작습니다(< 50개 instruction)
- .메모리에 저장된 명령어(코드/텍스트)를 기억합니다
- 코드 크기에 따라 가장 큰 분기 거리에 제한울 둡니다.
- PC(Program Counter)에 저장된 현재 명령어 주소
- PC 관련 주소 지정
- PC에 대한 두 개의 보완 오프셋으로 즉시 파일 사용이 가능합니다.
- 지점은 일반적으로 PC를 소량 변경합니다
- PC Register 에서 ±2^11 주소를 지정할 수 있습니다
- 바로 PC offset에서 바이트 오프셋을 사용하지 않는 이유는 무엇입니까?
- RISC-V는 32비트 주소를 사용하고 메모리는 바이트 주소를 사용합니다
- 명령어가 단어 정렬되어 있습니다(4의 배수)
- 바이트 대신 # 단어를 즉시 지정할 수 있습니다
- PC에서 ±2**11 바이트를 지정하는 대신, PC 주변에서 ±211 단어 = ±213 바이트를 지정할 수 있습니다.
- Branch를 take 하면
- PC = PC + (immediate * 4)
- Branch를 take 하지 않으면
- PC = PC + 4 # 다음 명령어 (Instruction)
- Observation
- 바로 앞(+) 또는 뒤(-)로 이동하라는 명령의 수입니다.
- 소스 레지스터 (rs1/rs2) 가 있고 12비트가 바로 있는 S-형식과 유사함
- 그러나 이제는 값 - 𝟐12 ~ 𝟐12 - 2바이트 단위의 증분 을 즉시 나타냅니다
- 12bit 즉시는 13비트 부호 오프셋까지 인코딩할 수 있습니다
- 이 오프셋의 가장 낮은 비트는 항상 0(짝수)이기 때문입니다.
SB-Format Example) beq x19, x10, offset # (offset = 16 byte)
Branch Offset = 4 x 32bit 명령어 = 16 Byte
Offset = 0→ branch 지침 자제
- beq: "branch if equal"의 약자로, x19와 x10 레지스터의 값이 같을 때 지정된 오프셋(offset)만큼 분기합니다.
- x19: 비교할 첫 번째 레지스터입니다.
- x10: 비교할 두 번째 레지스터입니다.
- offset: 조건이 참일 때 분기할 오프셋입니다. 이 오프셋은 바이트 단위이며, 이 명령어의 경우 16 바이트입니다.
- (offset = 16 byte) → 1000
- Branch는 offset 값 그대로 저장. 맨뒤 0 생략
RISC-V Instruction Type: U-Format
32비트를 즉시 처리하는 방법은 무엇일까요? 근데, I-type형은 12비트만 표시할 수 있습니다.
- Soultion: 20비트 나머지를 처리하기 위한 새 명령어 형식이 필요합니다
- 20비트를 입력할 대상 레지스터
- 20bit 즉시
- Opcode
- 두 가지 지침에 사용됩니다
- LUI : Load upper immediate
- AUIPC : PC에 Upper 즉시 추가
imm: 상위 20비트만 자릅니다.
lui x10, [0x87654] → 10번 Register에 상위 20비트 지정 (1자리당 4비트, 5자리)
addi x10, x10, [0x321] → i type 명령어 (12비트만 표현 가능)
RISC-V Instruction Type: UJ-Format
- Branch의 경우, 우리는 지금까지 분기하지 않을 것이라고 가정했기 때문에 PC Register 에서 변경 사항을 지정할 수 있습니다. → Branch 조건 검사후 맞으면 해당 Label로 분기 or Next 명령어를 실행합니다.
- 일반 점프(jal)의 경우, 우리는 메모리에서 어디든 점프할 수 있습니다.
- 이상적으로는 점프할 32비트 메모리 주소를 지정할 수 있습니다.
- 그러나 7비트 opcode와 32비트 주소를 모두 32비트 명령어에 맞출 수는 없습니다.
- 그리고 목적지 레지스터(5bit)를 연결해야 합니다.
goto문 → 무조건(조건 X), 분기 (jump 사용 - UJ Format의 명령어 Instruction)
ex) jump [이동해야할 주소 전달]
- jal은 register rd에 PC+4를 저장합니다 (return address) → Jump & Link Register → PC Register 주소 + rd (목적지 Register 주소 전달 - 4 byte)
- PC를 PC + Offset 설정
- PC 관련 주소 지정 → PC 상대 주소값
- ±2^19 (위치 / 2바이트 간격) 내 어딘가를 Target으로 합니다
- ±2^18 32비트 지침
imm: immdiate값: PC 주소로부터 얼마나 떨어져 있는지 Offset 주소값 관리 상수 입니다.
- j Label = jal x0, Label # 반환 주소(return address)를 x0으로 버립니다
- jal + 목적지 Register (ex-0번 register 지정 → 목적지 주소 안받음)
- Jal ra, Funcname (목적지 주소)
- PC의 ±218 명령어 내 Call Function
- j. jal → 목적지 주소 Yes or No? 그차이
- "j" jump는 수도 코드 입니다 (Compile X)
- 어셈블리는 대신 jal을 사용하지만 rd = x0 세트를 사용하여 return address를 폐기합니다
- 분기 명령어와 유사하게 최적화된 즉각적인 인코딩으로 하드웨어 비용을 절감할 수 있습니다.
- jair (jump & link register) instruction
- jalr rd, rs1, offset [r → rs1 (Base Address)]
- write PC+4 to rd (return address - 주소 반환)
- PC = rs1 + Offset 설정
- 연산 및 부하로 즉시 사용가능합니다. 또한 2바이트에 의한 곱셈이 없습니다.
반응형
'⚙️ Computer Architecture' 카테고리의 다른 글
[Computer Architecture] Operation (연산) (0) | 2024.07.15 |
---|---|
[Computer_Architecture] Instruction Set (0) | 2024.07.11 |
[Computer_Architecture] Performance Part.2 (0) | 2024.06.24 |
[Computer_Architecture] Performance Part.1 (0) | 2024.06.15 |
[Computer Architecture] Processor, Computer System Organization (0) | 2024.04.18 |