이 자료를 쓰는 강의: 40 Lec 5 · 성능 요약(평균·SPEC)과 single-cycle CPU datapath · 41 Lec 6 · control flow datapath 와 multi-cycle CPU(microcode)
Lec5-single-cycle-CPU
한국어판 강의자료 · 47쪽

p.1싱글 사이클 CPU

p.2세미나 안내
- 내일 오후 4시에 NVIDIA의 SuInn Park이 '자율 주행에서의 딥 뉴럴 네트워크 최적화' 주제로 세미나를 진행합니다.

p.3CPU: 명령어 처리 Finite-State machine (FSM)(유한 상태기계)
- ISA는 추상적인 유한 상태기계(FSM)를 설명한다.
- 상태 = program visible state(프로그램 가시 상태)
- 다음 상태 논리 = instruction execution(EX)(명령어 실행)
- 좋은 ISA는 atomic instruction semantics(원자적 명령어 의미)를 가진다.
- 추상 FSM에서 명령어 하나당 하나의 상태 전이가 발생한다.
- FSM의 구현 방식은 다양할 수 있다.
- I
- O
- S
- “Next”
- S
- 상태
- combinational logic(조합 논리 회로)
- combinational logic(조합 논리 회로)

p.4프로그램 가시(아키텍처) 상태
- 각 구성 요소의 입력과 출력은 무엇인가?
- PC
- register file(레지스터 파일)
- instruction memory(명령어 메모리)
- data memory(데이터 메모리)

p.5프로그램 가시(아키텍처) 상태
- 단일 메모리 공간

p.6마법 같은 메모리와 register file(레지스터 파일)
- combinational read(조합 논리 읽기)
- 읽기 데이터 포트의 출력은 register file(레지스터 파일)의 내용과 해당 읽기 선택 포트에 대한 조합 논리 함수이다.
- synchronous write(동기 쓰기)
- 선택된 레지스터(또는 메모리 위치)는 쓰기 허용 신호가 asserted(활성화)된 상승 에지 클럭 전이 시에만 업데이트된다.
- clock edge(클럭 엣지) 사이에 읽기 출력에 영향을 줄 수 없다.
- 프로그램이 LD(로드)될 때 instruction memory(명령어 메모리)도 쓰여야 하지만, 지금은 단순화를 위해 읽기 전용으로 간주한다.
- 메모리 계층 구조의 더 현실적인 설계는 나중에 배울 것이다.

p.7명령어 처리
- 5개의 일반적인 단계:
- IF: instruction fetch(명령어 인출)
- ID: instruction decode(명령어 디코딩) 및 operand fetch(피연산자 인출)
- EX: ALU/instruction execution(명령어 실행)
- MEM: memory access(메모리 접근) (로드 및 SD(스토어) 명령어에만 해당)
- WB: write-back(되돌려 쓰기)
- 레지스터
- 레지스터 번호
- 데이터
- 메모리
- 주소
- 데이터
- 레지스터 번호
- PC
- 명령어
- ALU
- instruction memory(명령어 메모리)
- 주소
- IF
- ID
- EX
- MEM
- WB

p.8내용
- ALU 명령어를 위한 datapath(데이터패스)
- LD/ST 명령어를 위한 datapath(데이터패스)
- 제어 흐름 명령어를 위한 datapath(데이터패스)
- 제어
- 오늘의 강의는 microarchitecture(마이크로아키텍처)에 관한 것입니다!
- microarchitecture(마이크로아키텍처)는 RISC-V 아키텍처를 구현합니다

p.9산술 및 논리 명령어를 위한 Single-Cycle datapath(싱글 사이클 데이터패스)

p.10리마인더: R-Type instruction(R형 명령어)
- 어셈블리 예시: ADD rd, rs1, rs2
- 인코딩:
- 의미:
- GPR[rd] ← GPR[rs1] □ GPR[rs2]
- [□: +, -, |, &, <<, >>, …]
- PC ← PC + 4
- 변형:
- 산술: ADD, SUB
- 비교(set less than(작으면 설정)): SLT (부호 있음), SLTU (부호 없음)
- 논리: AND, OR, XOR
- 시프트: SLL (왼쪽), SRL (논리 오른쪽), SRA (산술 오른쪽)
- 예외: 없음 (캐리 및 오버플로 무시)

p.11레지스터-레지스터 ALU datapath(데이터패스)
- PC
- instruction memory(명령어 메모리)
- 명령어 주소
- 명령어
- RegWrite
- 레지스터
- 쓰기 레지스터
- 읽기 데이터 1
- 읽기 데이터 2
- 읽기 레지스터 1
- 읽기 레지스터 2
- 쓰기 데이터
- 5
- 5
- 5
- 의미 (ADD):
- - GPR[rd] ← GPR[rs1] + GPR[rs2]
- - PC ← PC + 4
- 먼저 datapath(데이터패스)를 구축하고, 생성되어야 하는 control signal(제어 신호)를 식별합니다.
- 그 후, control signal(제어 신호)를 다룹니다.

p.12레지스터-레지스터 ALU datapath(데이터패스)
- PC
- instruction memory(명령어 메모리)
- 읽기 주소
- 명령어
- 4
- Add
- 레지스터
- 쓰기 레지스터
- 읽기 데이터 1
- 읽기 데이터 2
- 읽기 레지스터 1
- 읽기 레지스터 2
- 쓰기 데이터
- ALU result(ALU 결과)
- ALU
- zero(영 결과 신호)
- RegWrite
- ALU operation(ALU 연산 선택)
- 3
- 1
- 11:7
- 24:20
- 19:15
- func3, func7
- ([31:25], [14:12])
- 의미:
- - GPR[rd] ← GPR[rs1] + GPR[rs2]
- - PC ← PC + 4

p.13리마인더: I-Type instruction(I형 명령어)
- 어셈블리 예시: ADDI rd, rs1, imm12
- 인코딩:
- 의미:
- GPR[rd] ← GPR[rs1] □ sign-extend (immediate)
- [□: +, |, &, …]
- PC ← PC + 4
- 변형:
- 산술: ADDI, SUBI
- 논리: ANDI, ORI, XORI
- 비교(set less than immediate(즉시값 비교 설정)): SLTI (부호 있음), SLTIU (부호 없음)
- 예외: 없음 (캐리 및 오버플로 무시)

p.14레지스터-immediate(상수) ALU datapath(데이터패스)
- 어떻게 변경되어야 하는가?
- PC
- instruction memory(명령어 메모리)
- 읽기 주소
- 명령어
- 4
- ADD(덧셈)
- 레지스터
- 쓰기 레지스터
- 읽기 데이터 1
- 읽기 데이터 2
- 읽기 레지스터 1
- 읽기 레지스터 2
- 쓰기 데이터
- ALU result(ALU 결과)
- ALU
- zero(영 결과 신호)
- register write enable(레지스터 쓰기 허용)
- ALU operation(ALU 연산 선택)
- 3
- 1
- 11:7
- 24:20
- 19:15
- func3, func7
- 기본: [P&H CO&D, COPYRIGHT 2004 Elsevier. ALL RIGHTS RESERVED.]

p.15레지스터-immediate(상수) ALU datapath(데이터패스)
- 기본: [P&H CO&D, COPYRIGHT 2004 Elsevier. ALL RIGHTS RESERVED.]

p.16데이터 이동 명령어를 위한 Single-Cycle datapath(싱글 사이클 데이터패스)

p.17리마인더: LD(로드) 명령어 (I형)
- 어셈블리 예시 (더블워드 로드): LD rd, offset12(base)
- 인코딩:
- 의미:
- byte_address64 = sign‐extend(offset12) + GPR[base]
- GPR[rd] ← MEM64 [byte_address64]
- PC ← PC + 4
- 예외: 나중에 논의될 예정
- 변형:
- LD (더블워드)
- LW (워드), LH (하프워드), LB (바이트): sign extend(부호 확장)
- LWU, LHU, LBU: 0 확장
- rs1
- imm
- = 0000011

p.18LD(로드) datapath(데이터패스)
- LD(로드) 명령어에 대해 어떻게 변경되어야 하는가?
- 기본: [P&H CO&D, COPYRIGHT 2004 Elsevier. ALL RIGHTS RESERVED.]

p.19LD(로드) datapath(데이터패스)
- Registers
- Write register
- Read data 1
- Read data 2
- Read register 1
- Read register 2
- Data memory
- Write data
- Read data
- Write data
- Sign extend
- ALU result
- Zero
- ALU
- Address
- MemRead
- MemWrite
- RegWrite
- ALU operation
- 3
- Load Datapath
- Based on figures from [P&H CO&D, COPYRIGHT 2004 Elsevier. ALL RIGHTS RESERVED.]
- PC
- Instruction memory
- Read address
- Instruction
- 4
- Add
- 1
- ALUSrc
- isItype
- 12
- 64
- opcode, func3, func7
- isLoad
- 0
- 1
- Semantics:
- - byte_addr64 = sign-extend(offset12) + GPR[base]
- - GPR[rd] ← MEM64[byte_addr64]
- - PC ← PC + 4
- MemtoReg
- isLoad
- LoadExtend {W, H, HU, B, BU}
- 0
- 1

p.20SD(스토어) 명령어 리마인더 (S형)
- Assembly example (Store Doubleword): SD rs2, offset12(base)
- Encoding:
- Semantics:
- - byte_address64 = sign-extend(offset12) + GPR[base]
- - MEM64[byte_address64] ← GPR[rs2]
- - PC ← PC + 4
- Exceptions: will be discussed later
- Variations:
- - SD (doubleword)
- - SW (word), SH (halfword), SB (byte)
- Why split immediate?
- rs1
- imm
- = 0100011

p.21SD(스토어) datapath(데이터패스)
- How should this change for store?
- Semantics:
- - byte_address64 = sign-extend(offset12) + GPR[base]
- - MEM64[byte_address64] ← GPR[rs2]
- - PC ← PC + 4
- 16
- 32
- Registers
- Write register
- Read data 1
- Read data 2
- Read register 1
- Read register 2
- Data memory
- Write data
- Read data
- Write data
- Sign extend
- ALU result
- Zero
- ALU
- Address
- MemRead
- MemWrite
- RegWrite
- ALU operation
- 3
- Based on figures from [P&H CO&D, COPYRIGHT 2004 Elsevier. ALL RIGHTS RESERVED.]
- PC
- Instruction memory
- Read address
- Instruction
- 4
- Add
- 1
- ALUSrc
- isItype
- 12
- 64
- opcode, func3, func7
- isLoad
- 0
- 1
- MemtoReg
- isLoad
- LoadExtend {W, H, HU, B, BU}
- 0
- 1

p.22LD(로드)/SD(스토어) datapath(데이터패스)
- If STORE,
- isStore = 1
- → RegWrite = 0
- For others,
- isStore = 0
- → RegWrite = 1
- Semantics:
- - byte_address64 = sign-extend(offset12) + GPR[base]
- - MEM64[byte_address64] ← GPR[rs2]
- - PC ← PC + 4
- 16
- 32
- Registers
- Write register
- Read data 1
- Read data 2
- Read register 1
- Read register 2
- Data memory
- Write data
- Read data
- Write data
- Sign extend
- ALU result
- Zero
- ALU
- Address
- MemRead
- MemWrite
- RegWrite
- ALU operation
- 3
- PC
- Instruction memory
- Read address
- Instruction
- 4
- Add
- ALUSrc
- isItype
- || isStype
- 32
- 64
- opcode, func3, func7
- isLoad
- isStore
- Imm gen
- MemtoReg
- isLoad
- LoadExtend
- 0
- 1
- 0
- 1
- Based on figures from [P&H CO&D, COPYRIGHT 2004 Elsevier. ALL RIGHTS RESERVED.]
- !isStore

p.23비제어 흐름 명령어의 datapath(데이터패스)
- 16
- 32
- Registers
- Write register
- Read data 1
- Read data 2
- Read register 1
- Read register 2
- Data memory
- Write data
- Read data
- Write data
- Sign extend
- ALU result
- Zero
- ALU
- Address
- MemRead
- MemWrite
- RegWrite
- ALU operation
- 3
- Based on figures from [P&H CO&D, COPYRIGHT 2004 Elsevier. ALL RIGHTS RESERVED.]
- PC
- Instruction memory
- Read address
- Instruction
- 4
- Add
- !isStore
- ALUSrc
- isItype
- || isStype
- 32
- 64
- opcode, func3, func7
- isLoad
- isStore
- Imm gen
- MemtoReg
- isLoad
- LoadExtend
- 0
- 1
- 0
- 1

p.24제어 흐름 명령어의 Single-Cycle datapath(싱글 사이클 데이터패스)

p.25리마인더: 점프 명령어 (J형)
- - 점프 및 링크 어셈블리: JAL rd, imm21
- - 인코딩:
- 주의: imm[0] == 0 (짝수 주소로만 점프 가능)
- - 의미:
- target = PC + sign-extend(imm21) // PC-relative addressing
- GPR[rd] ← PC + 4 // 반환 주소를 레지스터에 저장 (BEQ/BNE와 비교)
- PC ← target // 항상 동일한 타겟으로 점프
- - 예외: misaligned target(잘못 정렬된 타겟) (4바이트)

p.26비조건적 점프 데이터패스 (JAL)
- - JAL에 대해 어떻게 변경되어야 하는가?
- - 의미:
- - target = PC + sign-extend(imm21)
- - GPR[rd] ← PC + 4
- - PC ← target
- - control signal(제어 신호):
- - isJ = 1
- - PCSrc = 1
- - PCtoReg = 1
- - RegWrite = 1
- - ALUSrc = 0
- - MemtoReg = 0
- - MemRead = 0
- - MemWrite = 0
- - ALU operation = ADD
- - Imm gen: sign-extend(imm21)
- - Add: PC + sign-extend(imm21)

p.27비조건적 점프 데이터패스 (JAL)
- - JALR에 대해 어떻게 변경되어야 하는가?
- - 의미:
- - target = PC + sign-extend(imm21)
- - GPR[rd] ← PC + 4
- - PC ← target
- - control signal(제어 신호):
- - isJ = 1
- - PCSrc = 1
- - PCtoReg = 1
- - RegWrite = 1
- - ALUSrc = 0
- - MemtoReg = 0
- - MemRead = 0
- - MemWrite = 0
- - ALU operation = ADD
- - Imm gen: sign-extend(imm21)
- - Add: PC + sign-extend(imm21)
- - 주의: 즉시값을 1비트 시프트하는 작업은 "Imm gen" 내에서 수행된다고 가정

p.28리마인더: 간접 점프 명령어 (I형)
- - 점프 및 링크 레지스터 어셈블리: JALR rd, imm12(rs1)
- - 인코딩:
- - 의미:
- target = GPR[rs1] + sign-extend(imm12) // 다른 타겟으로 점프 가능
- target &= 0xFFFF…FFFE // 최하위 비트를 0으로 설정
- GPR[rd] ← PC + 4
- PC ← target
- - 사용 사례:
- - 프로시저 반환: jalr x0, 0(x1) // x1로 반환. x0는 변경 불가능 (저장할 내용 없음)
- - 계산된 점프 (예: case/switch 문장)
- - 예외: misaligned target(잘못 정렬된 타겟) (4바이트)

p.29비조건적 점프 데이터패스 (JALR)
- - JALR에 대해 어떻게 변경되어야 하는가?
- - 의미:
- - target = GPR[rs1] + sign-extend(imm12)
- - target &= 0xFFFF…FFFE
- - GPR[rd] ← PC + 4
- - PC ← target
- - control signal(제어 신호):
- - isJ = 1
- - PCSrc = 1
- - PCtoReg = 1
- - RegWrite = 1
- - ALUSrc = 1
- - MemtoReg = 0
- - MemRead = 0
- - MemWrite = 0
- - ALU operation = ADD
- - Imm gen: sign-extend(imm12)
- - Add: GPR[rs1] + sign-extend(imm12)
- - Target 조정: target &= 0xFFFF…FFFE

p.30비조건적 점프 데이터패스 (JALR)
- - 의미:
- - target = GPR[rs1] + sign-extend(imm12)
- - target &= 0xFFFF…FFFE
- - GPR[rd] ← PC + 4
- - PC ← target
- - control signal(제어 신호):
- - isJ = 1
- - PCSrc = 1
- - PCtoReg = 1
- - RegWrite = 1
- - ALUSrc = 1
- - MemtoReg = 0
- - MemRead = 0
- - MemWrite = 0
- - ALU operation = ADD
- - Imm gen: sign-extend(imm12)
- - Add: GPR[rs1] + sign-extend(imm12)
- - Target 조정: target &= 0xFFFF…FFFE

p.31조건부 브랜치 명령어 (B형)
- 어셈블리 예시 (같을 때 브랜치): BEQ rs1, rs2, imm13
- 인코딩:
- 참고: imm[0] == 0 (짝수 주소로만 브랜치 가능) – 이는 괜찮은가?
- 의미:
- Target = PC + sign-extend(imm13) // PC-relative addressing
- If GPR[rs1] == GPR[rs2]
- then PC ← target
- else PC ← PC + 4
- 예외: 브랜치가 취해질 경우 misaligned target(잘못 정렬된 타겟) (4바이트)
- 변형
- BEQ, BNE, BLT, BGE (부호 있는 변형) – 왜 BGT (크다)는 없나?
- BLTU, BGEU (부호 없는 변형)
- = 1100111
- -- 얼마나 멀리 점프할 수 있는가?

p.32조건부 브랜치 datapath(데이터패스)
- Semantics (BEQ):
- Target = PC + sign-extend(imm13)
- If GPR[rs1] == GPR[rs2] then PC ← target
- else PC ← PC + 4

p.33조건부 브랜치 datapath(데이터패스)
- Semantics (BEQ):
- Target = PC + sign-extend(imm13)
- If GPR[rs1] == GPR[rs2] then PC ← target
- else PC ← PC + 4

p.34제어

p.35제어를 갖춘 datapath(데이터패스)
- Read register 1
- Write data
- Registers
- ALU
- Add
- bcond
- Read data 1
- Read data 2
- Instruction [31-0]
- ALU result
- Add
- Sum
- Addr
- Data memory
- Read data
- 4
- Read address
- Instruction memory
- PC
- ALU control
- Branch
- MemRead
- MemtoReg
- ALUOp
- MemWrite
- ALUSrc
- RegWrite
- Control
- Read register 2
- Write register
- Write data
- Imm Gen
- 32
- 64
- Instr [19-15]
- Instr [24-20]
- Instr [31-0]
- Instruction [30,14-12,6-0]
- Instr [6-0]
- Instr [11-7]
- 0
- 1
- 1
- 0
- 0
- 1
- 1
- 0
- JAL
- JALR
- 0
- 1
- PCtoReg
- PCSrc1
- PCSrc2

p.36단일 비트 control signal(제어 신호)
- When De‐asserted: RegWrite – GPR 쓰기 비활성화
- When asserted: RegWrite – GPR 쓰기 활성화
- Equation: (opcode!=SD/SW/SH/SB) && (opcode!=Bxx)
- When De‐asserted: ALUSrc – 2번째 ALU 입력은 2번째 GPR 읽기 포트
- When asserted: ALUSrc – 2번째 ALU 입력은 immediate(상수)
- Equation: (opcode!=IsRtype) && (opcode!=isBtype)
- When De‐asserted: MemRead – 메모리 읽기 비활성화
- When asserted: MemRead – 메모리 읽기 포트에서 LD(로드) 값 반환
- Equation: opcode==LD/LW/LH/LB
- When De‐asserted: MemWrite – 메모리 쓰기 비활성화
- When asserted: MemWrite – 메모리 쓰기 활성화
- Equation: opcode==SD/SW/SH/SB
- When De‐asserted: MemtoReg – ALU result(ALU 결과)를 GPR 쓰기 포트로 전달
- When asserted: MemtoReg – 메모리 LD(로드) 값을 GPR 쓰기 포트로 전달
- Equation: opcode==LD/LW/LH/LB
- When De‐asserted: PCtoReg – 위 결과를 GPR 쓰기 포트로 전달
- When asserted: PCtoReg – PC+4를 GPR 쓰기 포트로 전달
- Equation: opcode==JAL/JALR
- When De‐asserted: PCSrc1 – 다음 PC = PC + 4
- When asserted: PCSrc1 – 다음 PC = PC + immediate(상수)
- Equation: opcode==JAL || (opcode==Bxx && bcond)
- When De‐asserted: PCSrc2 – 다음 PC는 PCSrc1에 의해 결정됨
- When asserted: PCSrc2 – 다음 PC = GPR + immediate(상수)
- Equation: opcode==JALR

p.37다비트 제어 값
- 옵션
- 식
- ALUOp
- • ADD, SUB, AND, OR, XOR, NOR, LT 및 시프트
- • btype: EQ, NE, GE, LT
- case opcode
- RTypeALU: funct3, funct7[5]에 따라
- ITypeALU: funct3에 따라 (시프트 제외)
- LD/SD/JALR: Add
- Bxx: Subtract 및 btype 선택
- ImmGen
- I-type, I-typeU, S-type, B-type, U-type, J-type
- • 명령어 형식 유형에 따라 선택
- • (주 ALU와 PC-오프셋 가산기용 별도 확장 유닛을 사용하고자 할 수 있음)

p.38R형 ALU
- • GPR[rd] ← GPR[rs1] □ GPR[rs2]
- • PC ← PC + 4

p.39I형 ALU
- • GPR[rd] ← GPR[rs1] + sign-extend(imm)
- • PC ← PC + 4

p.40LD(로드)
- • byte_addr64 = sign-extend(offset12) + GPR[base]
- • GPR[rd] ← MEM64[byte_addr64]
- • PC ← PC + 4

p.41SD(스토어)
- • byte_address64 = sign-extend(offset12) + GPR[base]
- • MEM64[byte_address64] ← GPR[rs2]
- • PC ← PC + 4

p.42branch taken(브랜치 취함)
- • Target = PC + sign-extend(imm13)
- • If GPR[rs1] == GPR[rs2] then PC ← target
- • else PC ← PC + 4

p.43branch not taken(브랜치 미취함)
- instruction fetch(명령어 인출) (IF)
- register file(레지스터 파일)에서 레지스터 1 읽기
- register file(레지스터 파일)에서 레지스터 2 읽기
- instruction memory(명령어 메모리)에서 명령어 읽기
- PC + 4 계산
- ALU에서 조건 검사 수행
- ALU result(ALU 결과): GPR[rs1] == GPR[rs2]
- 브랜치 조건이 참이면 PC ← 타겟, 아니면 PC ← PC + 4
- 타겟 = PC + 부호 확장(imm13)
- GPR[rs1] == GPR[rs2] 이면 PC ← 타겟, 그렇지 않으면 PC ← PC + 4

p.44JAL
- instruction fetch(명령어 인출) (IF)
- register file(레지스터 파일)에서 레지스터 1 읽기
- register file(레지스터 파일)에서 레지스터 2 읽기
- instruction memory(명령어 메모리)에서 명령어 읽기
- PC + 4 계산
- 타겟 = PC + 부호 확장(imm21)
- GPR[rd] ← PC + 4
- PC ← 타겟

p.45JALR
- instruction fetch(명령어 인출) (IF)
- register file(레지스터 파일)에서 레지스터 1 읽기
- register file(레지스터 파일)에서 레지스터 2 읽기
- instruction memory(명령어 메모리)에서 명령어 읽기
- PC + 4 계산
- 타겟 = GPR[rs1] + 부호 확장(imm12)
- 타겟 &= 0xFFFF…FFFE (간단화를 위해 무시)
- GPR[rd] ← PC + 4
- PC ← 타겟

p.46이제 싱글 사이클 RISC-V CPU를 설계하는 방법을 알게 되었습니다!
- 그러나 이는 매우 느린 CPU입니다
- 다음 강의에서 더 빠른 다중 사이클 CPU 구현을 배웁니다

p.47질문?
- 공지사항
- 읽기: P&H (RISC-V ed.) Appendix C