Computer Architecture: RISC-V Data Path

상민·2024년 6월 21일

Computer Architecture

목록 보기
2/3

목차

명령어 수행 5단계

  1. IF (Instruction Fetch to Program Counter from memory)
  2. ID (Instruction Decode)
  3. EX (Execution) (일반적으로 ALU에서 동작하는 부분)
  4. MEM (Memory)
  5. WB (Write Back)

Datapath for instruction fetch

  • 다음은 PC(Program Counter)에서 다음 실행할 명령어를 fetch하고, decode를 위해 내보내는 과정이다.
  • Register -> ALU -> Register
  1. PC에 적혀있는 메모리 주소를 받아오면, 해당 주소의 메모리로 접근해 Instruction을 가져오고 decode를 위해 Instruction을 내보낸다.
  2. 명령어의 길이는 32bit(4byte)이므로 메모리 상 4칸 씩 띄워져있다. (한 메모리 주소 당 1byte 값을 저장하므로) 따라서 PC = PC+4 만큼 다음에 계산해 실행할 명령어(다음 줄의 명령어)를 PC에 저장할 수 있도록 Input에 넣고 대기한다.
  3. write enable 신호가 있는 상태에서, Clock Rising Edge를 만나면 PC의 state가 Input 값으로 바뀐다.

Datapath for R-Format Instruction

  • 다음은 R-format Instruction이 작동하는 과정이다.
  • Register -> (ImmGen) -> ALU -> DataMemory -> Register
  1. Instruction의 rs1 (5-bit), rs2, rd를 각각 받는다.
    • rs1: Read Register 1 (5-bit)
    • rs2: Read Register 2 (5-bit)
    • rd: Write Register (5-bit)
      • (General Purpose Integer Register는 32개가 있으므로 5-bit이다.)
  2. rs1과 rs2의 값을 ALU의 Input으로 넣어 계산한다.
    • ALU가 할 계산은 ALU Operation에 따라 정해지며, ALU Operation은 Instruction의 opcode, function bits을 보고 판단한다.
    • Input이 들어오면 바로 Output이 나온다. 왜냐하면 Combinational Logic 이기 때문에 edge rising을 기다릴 필요가 없다.
  3. 연산된 값은 rd에 적을 값의 input값으로 대기하고 있으며, RegWrite 신호가 활성화된 후 Clock Rising Edge를 만나면 rd의 state가 변경된다.

Datapath for Load or Store Instruction

  • 다음은 Load or Store Instruction이 작동하는 과정이다.
  • Register -> (ImmGen) -> ALU -> DataMemory -> Register
  1. Instruction의 rs1과 rd, 그리고 Immediate 값을 가져온다.
    • rs1: Read Register 1 (메모리 주소가 저장된 레지스터)
    • rd: Write Register (값을 저장할 레지스터 주소)
    • Imm12: (Offset 값)
  2. Imm12값은 Immediate Generator를 통해 64bit 명령어로 확장한다.
  3. rs1의 값(64bit)과 Immgen으로 만들어진 값(64bit)을 ALU를 통해 더한다.
  4. 더한 값을 메모리 주소로 하여금 접근해 MemRead 신호가 있을 경우 읽는다.
  5. 메모리에서 가져온 값을 rd 값의 input으로 대기하고, RegWrite 신호가 들어온 후 Clock Rising Edge를 만나면 rd의 state가 변경된다.

Datapath for Branch Instruction

  • 다음은 Branch Instruction이 작동하는 과정이다.
  • Register -> ALU -> ImmGen -> PC
  1. Instruction의 rs1과 rs2 값을 가져온다.
    • rs1: Read Register 1
    • rs2: Read Register 2
  2. ALU에서는 rs1과 rs2를 뺀 값이 0인지 확인하고 zero flag를 띄울지 판단한다.
  3. 조건에 만족할 경우 branch Immediate 값을 ImmGen을 거쳐 sign-extended 64-bit으로 바꾸고, shift left 1만큼 하여 PC를 변경한다
    • shift left 1을 하는 이유는 RISC-V는 16-bit Instruction도 지원하기 위해서이다.

Datapath: R-type + Load/Store

  • 다음은 R-type과 Load/Store를 합친 것이다.
  • R-type은 rs1, rs2가 있으며, Load/Store은 rs1만 있고, rs2 대신 Immediate 값이 온다. 따라 Mux로 값을 선택한다.
  • rd에 값을 적을 때, R-type은 ALU로 연산한 값이, Load/Store은 Memory로부터 읽은 값을 저장한다. 따라서 Memory 뒷 단에 Mux를 둔다. (앞 단이 아닌 뒷단인 것이 핵심이다.)
  • 각각의 Mux가 실행해야할 것들을 정하는 것은 Instruction Decode 단계에서 opcode를 기반으로 정해준다.
  • 핵심: rs2 vs Imm (ALUSrc), MEM vs ALURes (MemToReg)

Complete Single Cycle Datapath

  • 위 사진을 정확히 이해하자.
  • Control signal은 opcode와 function bit으로 만든다. (PCSrc 제외)
    • 모든 Controler signal은 Instruction을 보고 만들 수 있다 (X)
    • 대부분 Controler signal은 Instruction을 보고 만들 수 있다 (O)
    • PCSrc는 Branch Signal + ALU의 Zero Signal을 AND 연산하여 만든다.
  • ALU Control은 ALUOp(Opcode) + function bit으로 만든다.

Control Signal

  • Reg 1개, ALU 2개, Mem 3개, Branch 1개
  • Signal of R-Type (Register -> ALU -> Register)
    RegWrite: 1 (rd에 쓰는 작업이 있기 때문)
    ALUSrc: 0 (rs2 사용하기 때문)
    ALUOp: function bits에 따라 달라짐
    MemWrite: 0 (Memory 접근 X)
    MemRead: 0 (Memory 접근 X)
    MemtoReg: 0 (Memory에서 Reg로 가는 것이 아닌, ALU 값이 바로 Reg로 감)
    Branch: 0 (Branch 명령어 아님)

- Signal of Load (Register -> ImmGen -> ALU -> Mem -> Register)
RegWrite: 1 (rd에 쓰는 작업이 있기 때문)
ALUSrc: 1 (rs2가 아닌 Imm값을 사용)
ALUOp: ADD (offset 값을 항상 더함)
MemWrite: 0 (메모리 쓰기 작업 사용X, Store가 아님)
MemRead: 1 (Load이므로 Memory 읽기 작업)
MemtoReg: 1 (Memory에서 Reg로 바로 감)
Branch: 0 (Branch 명령어 아님)

- Signal of Store (Register -> ImmGen -> ALU -> Mem)
RegWrite: 0 (rd에 쓰는 작업 없음)
ALUSrc: 1 (rs2가 아닌 Imm값을 사용)
ALUOp: ADD (offset 값을 항상 더함)
MemWrite: 1 (Store이므로 Memory 쓰기 작업)
MemRead: 0 (메모리 읽기 작업 사용X, Load가 아님)
MemtoReg: X (메모리 쓴 후 명령어 종료)
Branch: 0 (Branch 명령어 아님)

- Signal of Branch (Register -> ImmGen -> ALU -> PC)
RegWrite: 0 (rd에 쓰는 작업 없음)
ALUSrc: 0 (rs2값 사용)
ALUOp: SUB (항상 빼기 연산을 통해 zero signal 여부를 판단)
MemWrite: 0 (Store이므로 Memory 쓰기 작업)
MemRead: 0 (메모리 읽기 작업 사용X, Load가 아님)
MemtoReg: X (메모리 쓴 후 명령어 종료)
Branch: 1 (Branch 명령어 아님)
(+) PCSrc: Branch AND Zero

profile
Today is flutter

0개의 댓글