[컴퓨터구조] 프로세서 1. RISC-V Datapath
Introduction
컴퓨터의 성능은 3가지 요소로 결정된다.
- Instruction count : ISA와 컴파일러
- Clock Cycle Time : CPU Hardware 에 의해 결정
- Clock Cycles Per Instruction (CPI): CPU Hardware에 의해 결정된다.
Basic RISC-V Implementation
RISC - V 에는 두가지 실행 버전이 있다.
- Simplified version
- pipeline version
여기선 다음 7개의 명령어만 구현한다.
- 메모리 참조 명령어 : ld, sd
- 산술 논리 명령어 : add, sub, and, or
- 조건부 분기 명령어 : beq
이러한 명령어를 구현하는 데 필요한 것은 대부분은 명령어가 어떤 명령어인지와 상관없이 동일하다.
코드를 포함하고 메모리로부터 명령어를 fetch 한 메모리에게 PC를 보낸다.
하나 혹은 2개의 레지스터를 읽는다.
위의 공통된 단계가 끝나면 각자의 명령어에 따라 수행하는 동작들이 달라진다.
RISC-V 명령어 집합의 단순함과 규칙적인 특성이 많은 종류의 명령어 실행을 비슷하게 만들어 줌으로써 구현을 단순화한다.
예를 들어 모든 명령어 종류는 레지스터를 읽은 후 ALU를 사용하는데, 각각의 목적은 다음과 같다.
- 메모리 참조 명령어(lw, sw)는 주소 계산을 위해 사용한다.
- 산술, 논리 명령어는 연산을 수행하기 위해 사용한다.
- 조건부 분기 명령어는 비교하기 위해서 사용한다.
Simplified version
위 5개 컴포넌트를 사용한다. (PC, Instruction memory, Registers, ALU, Data memory)
- PC에서 instruction memory를 참조하여 명령어를 가져온다.
- Register를 읽은 후에 ALU 명령어를 실행한다.
- 만약 Data memory를 참조해야 하는 일이 생긴다면 참조한다. (ld, sd 명령어 해당)
- add, sub 같이 register에 값을 쓰는 명령어라면 Register에 값을 입력한다.
- 1번 순서와 동시에 PC의 업데이트가 일어나는데, 만약에 명령어가 beq라면 PC + 4가 아닌 다른 방식으로 업데이트가 된다.
이 때 Clock cycle은 load가 걸리는 시간에 맞춘다. 모든 컴포넌트를 다 지나가야해 가장 오래 걸리기 때문이다.
산술 논리 명령어 예시
예를 들어 add x5, x6, x7을 실행한다고 가정할 때
- instruction fetch (add x5, x6, x7)
- register access (read x6, x7)
- addition (x6 + x7)
- 계산 결과를 x5에다가 write 한다
메모리 참조 명령어 예시
ld x5, 40(x6)을 실행한다고 가정할 때
- instruction fetch (ld x5, 40(x6))
- register access (read x6)
- memory address를 계산한다.
- 메모리를 읽는다. (x6 + 40) 그리고 x5 레지스터에 data를 write한다.
위 그림들은 프로세서 내의 데이터 흐름을 거의 다 보여주고 있지만 명령어 실행에 필요한 두 가지 측면이 제외되어 있다.
- data line은 고정되어 있지 않다.
- 서로 다른 source에서 나온 데이터가 같은 유닛으로 가는 곳이 몇 군데 있다.
- 예시
- PC에 들어가는 값은 두 개의 덧셈기에서 나온다. (하나는 4가 더해지고, 하나는 Instruction으로부터 나온다.)
- ALU의 두 번째 입력은 레지스터 혹은 명령어의 immediate 필드에서 나온다.
- 레지스터 파일에 쓰여질 데이터는 ALU나 Data memory에서 나온다.
- data path의 통제가 부족하다.
- 어떤 유닛들은 명령어 종류에 따라 다르게 제어되어야 한다.
- 예시
- 데이터 메모리는 적재 명령어일 때는 읽기, 저장 명령어일 때는 쓰기를 해야한다.
- ALU는 여러 연산 (더하기, 곱하기, 나누기, 빼기) 들 중 하나를 수행해야 한다.
위와 같은 두 가지 이유 때문에 멀티플렉스와 제어선을 추가하였다.
Multiplexer는 신호가 어느 방향으로 갈 지 정해준다.
Multiplexer는 Control 의 신호를 받아서 방향을 정한다.
control signal : Instruction register에 명령어가 올라가고 난 후 OP코드를 해석해서 제어 명령을 줄 수 있다.
ex) control 에서 write 시그널을 줘야 write를 할 수 있다.
ex) ALU operation도 control에서 준다.
ex) Data에 load가 저장될 지 ALU 계산값이 저장될 지 Mux에서 결정한다.
Processor = Datapath + Control
Logical Design
이진법으로 인코딩된 정보
datapath 는 두 가지 타입의 논리적 element 로 구성되어 있다.
- Combinational element : An operation element
- ALU 또는 And-gate
- 출력은 입력의 실행 결과
- State element : A memory element
- 레지스터 혹은 메모리
- 정보를 저장한다.
- state element는 적어도 2개의 입력과 하나의 출력을 가진다.
- 필요한 입력은 기록할 데이터 값과 데이터가 기록될 때를 결정하는 클럭
- 출력은 이전 클럭 사이클에서 작성된 값을 제공한다.
- Clock은 언제 state element가 써질지를 결정하고, 읽는 것은 아무때나 읽어도 된다.
- Sequential element
- 레지스터는 데이터를 저장하는 역할을 한다.
- 저장된 값을 클럭을 사용해 언제 업데이트 할 것인가.
- Edge-triggered F/F 를 가지고 레지스터를 만들었다.
- 한 비트의 데이터를 저장하기 위해 하나의 플립플랍이 필요하다.
- 엣지가 올라갈 때 데이터가 저장된다. = (Q에 d값이 반영된다.)
- 약간의 지연을 거쳐 Q가 반영된다.
- write 신호와 clock cycle이 둘 다 1일 때 D -> Q로 옮겨진다.
Clock Methodlogy
데이터를 읽고 써야 할 신호를 정의한다.
순차적인 논리적 element에 의해 저장된 값들이 오직 clock edge에 의해서만 업데이트 된다는 의미
clock edge에 의해 값들이 변경되는 것이 edge-triggered-methodology이다.
- Combinational logic은 clock cycle동안 data를 전송한다.
- clock cycle 사이에서 발생한다.
- state element로 부터 input을 받고, output을 state element로 보낸다.
- 가장 긴 delay가 clock period를 결정한다.
Building Data path
Datapath : 프로세서 내에서 데이터를 작동하거나 보유하는 데 사용되는 단위
Instruction Fetch
- 명령어를 실행하기 위해 필요한 3가지 요소
- memory unit: 주어진 주소에 명령어를 저장하거나, 주소가 주어지면 해당 주소에 저장된 명령어를 보내준다.
- PC(Program Counter) : 현재 실행하는 instruction의 주소를 저장한다.
- adder : PC를 다음 명령의 주소로 증가시킨다. (Adder != ALU)
명령어를 실행하기 위해서는 메모리에서 명령어를 가져오는 (fetch) 것으로 시작해야 한다.
다음 명령어 실행을 준비하기 위해서 프로그램 카운터가 다음 명령어를 가리키도록 4만큼 증가시켜야 한다.
이 세개에 대해서는 Control Signal이 다 필요 없다.
Instruction memory에서는 읽기만 하고, Adder에서는 더하기만 하고, PC는 새로운 신호가 들어오면 update하기 때문에
또한 입력에 따라 출력값이 결정되는 Combinational Logic을 쓰면 된다.
R - format Instruction
모든 R-format 명령어들은 2개의 레지스터를 읽고, 해당 값들을 통해 ALU 연산을 수행하며 그 결과를 레지스터에 쓴다.
해당 명령어에는 add, sub, and, or 명령어를 포함하고 있다.
프로세서의 범용 레지스터 32개는 레지스터 파일 (register file) 속에 들어있다.
이는 레지스터를 모아놓은 것으로 , 파일 내의 레지스터의 번호를 지정하면 어떤 레지스터라도 읽고 쓸 수 있다.
- R-format 명령어들은 레지스터 피연산자를 3개 가지고 있어, 매 명령어마다 레지스터 파일에서 두 데이터를 읽고 데이터 하나를 써야 한다.
- 레지스터에서 데이터를 읽기 위해서는 레지스터의 입력과 출력이 한 번 씩 필요하다.
- 읽을 레지스터 번호를 지정하는 입력
- 읽은 값을 내보내는 출력
- 데이터를 쓰기 위해서는 입력이 2개 필요하다.
- 한 입력은 레지스터 번호를 지정하고
- 다른 입력은 레지스터에 쓸 데이터 값을 제공한다.
레지스터 파일은 Read register 입력에 제공되는 번호에 해당하는 레지스터의 내용을 항상 출력한다.
그러나 쓰기는 쓰기 제어 신호에 의해 제어되므로 클럭 에지에서 쓰기가 발생하기 위해서는 해당 제어 신호가 1이 되어야 한다.
따라서 전체적으로 입력 4개 (레지스터 번호 3개와 데이터 1개) 와 출력 2개 (모두 데이터) 가 필요하다.
- 입력
- 읽을 레지스터 번호 1
- 읽을 레지스터 번호 2
- 쓸 레지스터 번호
- 레지스터에 쓸 데이터 값
- 출력
- 읽은 데이터 값 1
- 읽은 데이터 값 2
ALU에서는 그 두개의 데이터를 받아서 원하는 operation을 수행하는데, 4bit의 control signal로 원하는 operation을 수행할 수 있도록 한다. Zero가 되는 경우 1 bit의 signal을 내보낸다.
register가 이동하는 datapath는 5bit만 할당한다. (x0 ~ x31 까지 있기 때문에)
data는 32-bit
load / store instruction
이 명령어는 base address + offset의 주소에서 data를 읽어와서 특정 register에 저장하거나, 아니면 base address + offset 의 주소에 원하는 register의 값을 저장한다.
따라서, register file과 메모리 주소를 계산하는 데 사용될 ALU가 동시에 필요하다.
또한 offeset의 값이 12bit의 immediate value 이므로, 이를 64bit로 sign-extend 하는 유닛이 필요하며
읽고 쓸 데이터 메모리가 필요하다.
데이터 메모리는 저장 명령일 때만 쓰기를 해야 한다.
따라서 데이터 메모리는 읽기 제어 신호 (올바르지 않은 주소의 값을 읽는 것을 방지하기 위해) 와 쓰기 제어 신호, 주소입력, 메모리에 쓸 데이터 입력이 필요하다.
Branch Instruction
3개의 피연산자를 갖는데, 2개의 레지스터와 12비트의 offset이다.
2개의 레지스터는 같은지 비교될 피연산자이며,
12비트 offset은 분기 명령어의 주소에 대한 상대적인 분기 목적지 주소를 계산하는 데 사용되는 값이다.
이 명령어를 구현하기 위해서는 PC 값에다가 offset 필드를 부호확장한 값을 더해서 분기 목적지 주소를 계산해야 한다.
분기 명령어에서는 주의해야 할 점이 있는데
분기 주소 계산의 베이스 주소는 분기 명령어 주소이다.
변위 필드는 하프워드 변위이므로, 왼쪽으로 1비트 만큼 자리이동 하여야 한다.
분기 목적지 주소를 계산하는 것 외에도, 분기 명령어는 두 피연산자 레지스터가 동일한지의 여부를 통해 다음 명령어로 받아올 주소가 달라진다.
두 피연산자 값이 같을 때 분기 목적지 주소가 새로운 PC값이 되며, 이때 분기가 일어났다(taken)라고 말한다.
두 피연산자 값이 다를 때에는 다른 명령어와 동일하게 PC의 값이 4 증가되며, 이 값이 새로운 PC값이 된다.
따라서 Branch instruction은 두 가지 작업을 한다.
- branch target address를 계산한다.
- Immgen + Address
- 레지스터의 내용을 Test -> 두 개의 레지스터를 빼서 0인지 체크하고 그 결과를 ALU에게 준다.
- 뺄셈을 하도록 만드는 제어 신호를 ALU에 함께 보낸다.
레지스터 내용의 비교는 ALU를 통해 이루어지며, 뺄셈을 하도록 만드는 제어 신호를 ALU에 함께 보낸다.
Full Datapath
위에서 살펴본 데이터 패스 구성 요소들을 하나로 묶고 여기에 제어를 추가하여 데이터 패스의 구현을 완성할 수 있다.
모든 명령어가 한 클럭 사이클에 실행되도록 할 것이므로, 어느 데이터 패스 자원도 명령어 당 두 번 이상 사용될 수 없다.
예시 1
Instruction add x5, x6, x7이 들어왔다고 가정해보자,
- 우선 instruction memory에서 fetch 한다.
- 그리고 Read register1, 2에 x6, x7을 각각 넣어준다. 이 때 datapath는 5-bit
- register1, 2에 있는 data를 읽어서 ALU에 전달
- 두 개의 data를 ALU에서 ALU operation에 의해서 연산을 하고 그 결과를 data memory로 보내거나 데이터 메모리를 거치지 않고 바로 write data로 넘어가서 write register인 x7에 값을 작성한다.
- 실행이 완료되었으므로 x7에 값을 작성한다.
예시 2
beq x5, x6, offset 이 들어왔다고 가정하자
- instuction memory에 fetch한다.
- Read register1, 2에 x5, x6을 넣어준다.
- beq 명령어이기에 ALU에서 x5와 x6을 sub 해준다.
- 여기서 결과가 0이라면 zero에 신호가 가서 pc + offset에 해당하는 값이 PC에 저장
- 결과가 0이 아니라면 기존에 진행하던 PC + 4의 값이 PC에 저장된다.
ALU Control
- Load / Store : Function = add
- Branch : Function = subtract
- R-type : func7, func3의 값에 따라 뭘 할지 결정
- 2-bit ALUOp로부터 어떤 명령어인지 찾는다.
- R-type인 경우 ALUOp가 다 같아서 -> func 필드 참조
- ALUOp 11 사용하지 않는 이유 -> 최대한 활용해서 combination logic을 간단하게 하기 위해
많은 경우의 수를 최적화 한 테이블이다.
실제로 input에 따른 경우의 수는 $2^12 = 4096$ 인데 그건 너무나 많은 경우의 수가 있다. 그래서 특정 값을 기준으로 바로바로 최적화 할 수 있다.
Datapath with Control
Control Signals
컨트롤 유닛의 명령의 opcode 및 funct 필드만을 기준으로 제어 신호 중 하나를 제외한 모든 것을 설정할 수 있다.
PCsrs 컨트롤라인은 예외다
beq 명령어에서 ALU의 0 출력이면 PCsrs가 asserted
- Signal name
- Regwrite
- 신호가 1일 때 : write register 입력의 레지스터는 write data input으로 기록된다.
- 신호가 0일 때 : 아무일도 발생하지 않는다.
- ALUSrc
- 신호가 1일 때: 두 번째 ALU operand은 sign-extended instruction 의 12비트 (offset)
- 신호가 0일 때 : 두 번째 ALU operand는 register 2 출력에서 나온다
- PCSrc
- 신호가 1일 때 : pc는 branch target을 계산하는 adder의 출력으로 대체된다.
- 신호가 0일 때 : pc는 pc + 4의 값으로 대체된다.
- MemRead
- 신호가 1일 때 : 주소 입력에 의해 지정된 데이터 메모리 내용이 읽기 데이터 출력에 저장된다.
- 신호가 0일 때 : 아무일도 발생하지 않는다.
- MemWrite
- 신호가 1일 때: 주소 입력에 의해 지정된 데이터 메모리 내용이 Write data input으로 대체된다.
- 신호가 0일 때 : 아무일도 발생하지 않는다.
- MemtoReg
- 신호가 1일 때 : register에 입력된 값 write data input은 데이터 메모리에서 가져온다.
- 신호가 0일 때 : register에 입력된 값 write data input은 ALU에서 가져온다.
- Regwrite
명령어 type에 따른 Control Signal의 여부
참고
https://jja2han.tistory.com/207
[Computer Architecture] - processor (1)
📕Introduction 컴퓨터의 성능은 3가지 요소로 결정된다. Instruction count : ISA와 컴파일러 Clock Cycle time : CPU hardware에 의해 결정된다. Clock Cycles Per Instruction(CPI) : CPU Hardware에 의해 결정된다. 📕Basic RISC
jja2han.tistory.com
https://ttl-blog.tistory.com/1033
[컴퓨터 구조] 프로세서[0] - 데이터패스 구현
🧐 기본적인 RISC-V 구현 개요 이제부터 다음 핵심적인 명령어들을 실행하기 위한 프로세서를 설계하는 과정을 통해, 프로세서에 대해 알아보도록 하겠습니다. 메모리 참조 명령어 : ld, sd 산술
ttl-blog.tistory.com
https://oilbeen.tistory.com/17?category=929994
RISC-V 컴퓨터구조 - 4. The Processor - 4.3. Building a Datapath
이 장에서는 각 instruction에 필요한 datapath elements를 분석해본다. Instruction Fetch 일단 첫 번째로 필요한 element는 (a) program의 instruction을 저장하고 주어진 address의 instruction을 주는 memory unit (b) PC(Program
oilbeen.tistory.com
https://luv-n-interest.tistory.com/992
Datapath, Simple Implementation Scheme & Pipelineing [컴퓨터구조]
지금까지 배운 것은 다 이것을 위한 필수 지식에 불과했다. 진짜 이제부터 하나하나씩 뜯으면서 보자. 먼저 ALU에 대한 것 부터 배워야 한다. **ALU Control은 4-bit 이다. 또 ALU를 Control 하는 2-bit가 있
luv-n-interest.tistory.com