4.1 Introduction
A Basic RISC-V Implementation
메모리 참조 명령어 : lw, sw
산술 및 논리연산 명령어 : add, sub, and, or
조건 분기 명령어 : beq
위 7가지 명령어들은 RISC-V 명령어들의 일부분을 나타낸 것이다.
이것들 이외에 다양한 명령들이 있지만,
위 구성을 이용한 구현을 통해 datapath, designing control 의 설계의 근본을 이해할 수 있다.
1장에서 나온 원칙 중 하나 "Simplicity favors regularity" 가 여기서 강조된다.
An Overview of the Implementation
-RISC-V의 기본 데이터 경로.
• Instruction Memory: 명령어 메모리에서 명령어를 가져옵니다. 이때 프로그램 카운터(PC)를 사용하여 현재 실행 중인 명령어의 위치를 가리킨다.
• Registers: 명령어에서 지정된 두 개의 레지스터를 읽고, 필요한 경우 결과를 레지스터 파일에 다시 쓴다.
• ALU (Arithmetic-Logical Unit): 산술 또는 논리 연산을 처리하는 유닛으로, 대부분의 명령어가 이 유닛을 통해 연산된다.
• Data Memory: lw나 sw 같은 메모리 참조 명령어에서 데이터를 읽거나 쓸 때 사용하는 메모리이다.
• PC (Program Counter): 다음 명령어의 위치를 가리키는 포인터로, 매번 명령어가 실행될 때마다 갱신된다.
- 위 그림에 MUX(multiplexer) 와 control line을 추가한 그림이다.
MUX의 값에 따라 들어온 두 개의 데이터 중 어떤 데이터가 나올지 결정된다.
제일 위쪽의 MUX의 경우, beq의 결과에 따라 MUX의 값이 결정되며
beq의 조건이 참이면 PC = PC + imm(분기할 주소) 가 되고,
beq의 조건이 거짓이라면 PC = PC+4(다음 명령어의 주소) 가 된다.
중간 MUX의 경우, 그 값에 따라
ALU에서 읽어온 값 / 데이터 메모리에서 읽어온 값 중
어떤 값을 레지스터 파일에 쓸지 결정된다.
하단의 MUX의 경우,
ALU에 들어갈 값이 imm인지, 레지스터에서 읽어온 값인지 결정한다.
Control (Regwrite, MemRead 등..)에 따라 어떤 작업을 할지 결정된다.
• RegWrite: 명령어가 실행된 후 결과를 레지스터에 쓸지 여부를 결정한다. (lw나 add와 같은 명령어에서 사용).
• MemRead, MemWrite: 메모리에서 값을 읽을지 또는 메모리에 값을 쓸지 결정한다. (lw, sw 명령어).
• Branch: 분기 명령어(beq)에서 사용되며, ALU가 두 레지스터를 비교한 결과에 따라 다음 명령어의 주소를 결정한다.
\
작동 과정
• 메모리 참조 명령어 (lw, sw):
1. 명령어 메모리에서 명령어를 가져온다.
2. 명령어에서 읽을 레지스터를 결정하고 해당 레지스터에서 값을 읽는다.
3. ALU를 사용하여 메모리 주소를 계산한다.
4. lw는 계산된 주소에서 값을 읽어 레지스터에 쓰고. sw는 레지스터에 있는 값을 계산된 주소에 쓴다.
• 산술 논리 명령어 (add, sub, and, or):
1. 명령어 메모리에서 명령어를 가져온다.
2. 레지스터 파일에서 두 개의 레지스터 값을 읽는다.
3. ALU를 사용하여 산술 또는 논리 연산을 수행한다.
4. 연산 결과를 다시 레지스터 파일에 쓴다.
• 조건 분기 명령어 (beq):
1. 명령어 메모리에서 명령어를 가져온다.
2. 두 개의 레지스터 값을 읽고, ALU에서 이 값들이 같은지 비교한다.
3. 결과에 따라 프로그램 카운터(PC)를 갱신.
Check Yourself
-five classic components of a computer
1. input
2.output
3.datapath
4.control
5.memory
4.2 Logic Design Conventions
-RISC-V 설계에서 사용되는 두가지 논리 요소.
1. Combinational Element
공간이 없어 즉시 값을 출력하고, 같은 값에는 항상 같은 값을 출력함 (ex. ALU, gate)
2. State Element
값을 저장할 수 있고, 필요할 때 그 값을 출력할 수 있음.
적어도 두 개의 입력(하나는 데이터 값, 하나는 클럭)을 받고, 출력은 클럭사이클에 쓰여진 값.
ex) 레지스터, 메모리, D-type flip-flop
state를 가지는 논리요소를 sequential 이라 부른다.
입력 뿐만 아니라 원래 가지고 있던 것의 상태에도 영향을 받기 때문이다.
예를 들어, 레지스터의 출력은 레지스터의 번호와 이전에 있던 데이터에 의해 결정된다.
Clocking Methodology
clocking methodology는 신호를 언제 일고 언제 써야하는지를 정의한다.
데이터를 읽고 쓰는 타이밍을 못 맞추면 데이터가 섞이거나 혼동이 될수 있기에 중요하다.
edge-triggered clocking
Check Youself
레지스터 파일은 동일한 clock cycle에 읽고 써지기 때문에, edge-triggered를 사용하면 여러개의 레지스터 파일을 사용할 수 있기 때문에 여러개의 레지스터 파일을 사용하는 것이 성능 최적화에 중요하다.
4.3 Building a Datapath
-R type Instruction
두 개의 레지스터 값을 읽은 뒤 ALU 연산을 수행하고, 그 결과값을 레지스터에 넣는 명령어.
add, sub, and ,or 등이 여기에 해당.
R format 명령어를 수행하기 위해서는
1. register file
2. ALU
가 필요하다.
레지스터 파일은 프로세서의 32개의 일반 레지스터들이 포함된 구조이다.
ALU의 연산은 ALU control signal에 의해 결정되는데 이는 4비트이다.
-lw, sw
이 메모리 참조 명령어들은 base register에 12bit imm을 더해 메모리 주소를 계산한다.
이 imm을 sign-extend하여 32비트로 확장해 사용한다.
lw는 메모리에서 데이터를 읽어와 레지스터에 저장하고,
sw는 레지스터에서 데이터를 읽어와 메모리에 저장한다.
이를 위해 data memory unit, imm Gen 이 필요하다.
-beq
3개의 operands( 같은지 비교할 2개의 레지스터, 분기할 주소를 계산할 12비트 imm)를 가진다.
분기 명령어의 offset field는 half word offset이기 위해 왼쪽으로 1비트 쉬프트한다.(2배)
ALU에서 조건을 확인하며 조건을 충족할 때 zero signal을 발생시켜 분기시킨다.
Creating a Single Datapath
-Example (Building a Datapath)
arithmetic-logical(R-type) 명령어와 메모리 참조 명령어는 꽤나 유사하다.
차이점
- arithmetic-logical 명령어는 두개의 레지스터에서 값을 읽어와 ALU의 입력값으로 사용하고,
메모리 참조 명령어 또한 ALU를 사용하지만, 주소계산을 하는데 사용한다.
- ALU에서 계산된 값은 목적지 레지스터에 저장되거나 메모리에 저장된다.
단일 ALU, register file을 이요하여 datapath를 만드려면 다음과같은 것들이 필요하다.
- ALU에서 두 번째 값을 선택할 수 있는 MUX가 필요하다.
- 결과를 메모리에서 읽어올지, RegWrite를 할지 결정하는 MUX가 필요하다.
Check Yourself
1. Which of the following is correct for a load instruction?(Figure 4.10)
a. MemtoReg should be set to cause the data from memory to be sent to the register file.
b. MemtoReg should be set to cause the correct register destination to be sent to the register file.
c. We do not care about the setting of MemtoReg for loads.
ans
MemtoReg는 메모리에서 읽어온 데이터를 레지스터로 보내기 위함이다.
a에서 그 설명을 하고 있으므로 답은 a이다.
2. The single-cycle datapath conceptually described in this section must have separate instruction and data memories, because -----
a. the formats of data and instructions are different in RISC-V, and hence different memories are needed;
b. having separate memories is less expensive
c. the processor operates in one clock cycle and cannot use a (single-ported) memory for two different accesses within that clock cycle.
ans
단일 메모리로는 명령어 패치, 데이터 읽기, 데이터 쓰기를 동시에 할 수 없기에 단일 사이클 datapath에서는 별도의 메모리 사용이 필요하다. 따라서 정답은 c이다.
4.4 A Simple Implementation Scheme
The ALU Control
RISC-V ALU는 위의 4가지 연산을 수행할 수 있다.
lw / sw 의 경우 add연산을 통해 메모리 주소를 계산하고,
R-type 명령어의 경우 명령어 내부의 funct7, funct3필드를 확인해 필요한 연산을 하며,
beq의 경우 sub연산을 통해 조건을 확인하고 분기한다.
ALUOp
2비트 control field로 어떤 작업을 수행할지 결정하는 역할을 한다.
ALU control signal 은 ALUOp, funct3, funct7가 결합하여 4비트로 생성된다.
• 로드 (lw) 및 스토어 (sw) 명령어
funct7와 funct3 값과 상관없이 add 연산이 필요하므로, ALU는 0010 신호를 받는다.
• 분기 (beq) 명령어
subtract 연산이 필요하므로, ALU는 0110 신호를 받는다.
• R형 명령어:
• add: funct7 = 0000000, funct3 = 000일 때 add
• sub: funct7 = 0100000, funct3 = 000일 때 subtract
• and: funct7 = 0000000, funct3 = 111일 때 and
• or: funct7 = 0000000, funct3 = 110일 때 or
Designing the Main Control Unit
1. opcode field
명령어의 형식과 동작을 결정하는 필드 (7비트)
2. rs1
피연산자 레지스터(5비트)
값을 읽어오는 base register / lw,sw명령에서 주소계산하는데 사용
3. rs2
두번쨰 피연산자 레지스터(5비트)
sw에서 메모리에 저장할 값 제공
4. 피연산자는 레지스터가 아닌 Imm이 될 수 있다.
5. rd
목적지 레지스터
lw명령어는 데이터를 불러와 여기에 저장하고 산술연산명령어는 결과를 여기 저장한다.
Simplicity favors regularity
MIPS와 비교.
MIPS는 목적지 레지스터를 구분하기 위해 MUX를 사용하지만,
RISC-V는 rd를 항상 같은 비트 범위에 위치시켜 속도를 올렸다.
또한, SB, UJ와 같은 형식을 통해 분기 및 점프를 단순하였다.
주요 제어 신호:
1. RegWrite:
• 비활성화 상태: 아무 일도 일어나지 않음.
• 활성화 상태: 레지스터에 데이터를 기록함.
2. ALUSrc:
• 비활성화 상태: 두 번째 ALU 피연산자는 레지스터 파일에서 출력된 값이 됨.
• 활성화 상태: 두 번째 ALU 피연산자는 즉시값(12비트 확장된 값)이 됨.
3. PCSrc:
• 비활성화 상태: PC는 PC + 4로 대체됨.
• 활성화 상태: PC는 분기 타겟 주소로 대체됨.
4. MemRead:
• 비활성화 상태: 메모리에서 읽지 않음.
• 활성화 상태: 메모리에서 데이터를 읽어 해당 주소의 값을 출력함.
5. MemWrite:
• 비활성화 상태: 메모리에 아무것도 기록하지 않음.
• 활성화 상태: 메모리의 특정 주소에 데이터를 기록함.
6. MemtoReg:
• 비활성화 상태: 레지스터 파일에 기록될 데이터는 ALU에서 나온 값임.
• 활성화 상태: 레지스터 파일에 기록될 데이터는 메모리에서 읽은 값임.
Operation of the Datapath
-R type
1. 명령어 메모리에서 명령어를 읽어오고 PC+4 (다음 명령어)
2. 레지스터 파일에서 두 레지스터의 값을 읽는다.
3. ALU가 연산을 수행하고 그 결과가 출력으로 나온다.
4. 출력으로 나온 값이 목적지 레지스터에 저장된다.
-load 명령어
1. 명령어 메모리에서 명령어를 읽어온다.
2. 레지스터 파일에서 레지스터(x2)를 읽는다.
3. ALU가 레지스터 파일에서 읽어온 값과 12비트 상수를 sign extension한 값을 더해 메모리 주소를 계산하고 그 값을 읽는다.
4. 읽은 데이터를 레지스터(x1) 에 쓰인다.
-beq
1. 명령어 메모리에서 명령어를 읽어온다.
2. 레지스터 파일에서 두개의 레지스터 값을 읽는다.
3. ALU는 substraction연산으로 두 값이 같은지 판단한다.
4. 그 결과가 zero라면 Mux값이 1로 설정되어 PC= PC + imm (분기)
Finalizing Control
아래 표는 명령어 별 opcode(7비트, 인풋)와 control function을 보여준다.
Why a Single-Cycle Implementation is not Used Today
- 가장 오래 걸리는 것을 기준으로 삼기 때문에 오래 걸린다.
- 하드웨어 구현은 단순하지만 비효율적.
Common case fast
4.5 A Multicycle Implementation
multicycle은 각 명령어를 여러 단계로 쪼개는 것이다.
각 단계를 한 사이클이라 칭할 것이고, 따라서 명령어의 종류가 다르면 사이클의 수가 달라지므로 CPI도 달라진다.
Multicycle Divisions
다음과 같은 5단계로 쪼갤 수 있으며, 명령어별로 조금씩 다르다.
1. Instruction Fetch (IF)
2. Register Fetch (RF)
3. Execute (EX)
4. Memory Access (MEM)
5. Write Back (WB)
다음은 multicycle의 대략적인 작동방식을 보여준다.
빨간 글씨로 써져있는 것이 레지스터이고, 이는 값을 임시로 저장하기 위해 사용된다.
(그림에서의 크기는 다르지만 실제로는 같은 크기를 가지고 있다. 레지스터 하나이기 때문)
Single Cycle과 달리, ALU가 하나만 있다.
여러 연산이 동시에 수행되어야 한다면 ALU가 여러개 있어야 하지만,
그게 아니므로 하나의 ALU가 여러 작업을 다른 시간대에 수행할 수 있다.
다음 표는 RTL수준으로 작성한 명령어별 코드를 보여준다.
각 명령어별로 어떻게 작동하는지 알아보자.
R-type
step 1. Instruction Fetch
IR = Mem[PC]
PC = PC + 4
step 2. Instruction Decode and Register Fetch
A = Reg[IR[19-15]]
B = Reg[IR[24-20]]
step 3. R-Type Execution
ALUOut = A op B
step 4. R-Type Completion step
Reg[IR[11-7]] = ALUOut
lw
step 1. Instruction Fetch
IR = Mem[PC]
PC = PC + 4
step 2. Instruction Decode and Register Fetch
A = Reg[IR[19-15]]
step 3. Memory Execution
ALUOut = A + sign-extend(imm12)
step 4. Load Memory Access Step
MDR = Memory[ALUOut]
step 5. Load Completion Step
Reg[IR[11-7]] = ALUOut
sw
step 1. Instruction Fetch
IR = Mem[PC]
PC = PC + 4
step 2. Instruction Decode and Register Fetch
A = Reg[IR[19-15]]
B = Reg[IR[24-20]]
step 3. Memory Execution
ALUOut = A + sign-extend(imm12)
step 4. Store Memory Access Step
Memory[ALUOut] = B
beq
step 1. Instruction Fetch
IR = Mem[PC]
PC = PC + 4
step 2. Instruction Decode and Register Fetch
A = Reg[IR[19-15]]
B = Reg[IR[24-20]]
ALUOut = PC + Branch Label
step 3. Branch Completion Step
if(A==B) PC = ALUOut
else PC = PC + 4
'Book > COMPUTER ORGANIZATION AND DESIGN RISC-V' 카테고리의 다른 글
4. The Processor (4.6. Data Hazard) (1) | 2024.11.15 |
---|---|
4. The Processor (4.6. An Overview of Pipelining) (0) | 2024.11.15 |
2. Instructions:Language of the Computer(2.11~2.14, 2.23, 2.25) (6) | 2024.10.06 |
2. Instructions:Language of the Computer(2.1~2.10) (4) | 2024.10.06 |
Operations (1) | 2024.10.05 |