반응형
전체 datapath 구조
몇가지 살펴볼점
- pc + 4 연산 Add
- 명령문 = 32bit = 4byte
- 따라서 4만 더해주면 다음 명령어를 가리킬 수 있게 되서 4를 더함
- Instruction memory와 Data memory
- 둘다 어떻게 보면 메모리(정확하게는 캐시)인데 둘을 구분하는 이유
- structure hazard 때문
- 두 메모리가 합쳐져 있다면 data memory에 접근 시 instruction 메모리에 접근할 수 없기때문에 파이프라이닝이 불가능(5장 내용과 관련)
- 둘다 어떻게 보면 메모리(정확하게는 캐시)인데 둘을 구분하는 이유
- Control signal
- Branch : 분기문일때만 1(이후는 0이라 상대 주소를 활용할 일이 없음)
- MemRead
- Data memory에서 메모리를 읽을지(load)
- MemWrite
- Data memory에서 메모리를 쓸지(store)
- Writedata의 값을 address가 가리키는 메모리에 작성
- 이때, Read data는 쓰레기 값
- 쓰레기값이지만 사용하지 않더라도 다른곳에서 사용할 수 있기에 mux에 연결되어 있음
- 항상 read data의 output자체는 존재함(사용안될때는 쓰레기값이 나옴)
- 따라서 alu result가 readdata중 값을 선택해야 하기에 mux존재(MemToReg가 결정)
- 쓰기, 읽기, 동작x까지 총 3개의 동작을 표현하기 위해 2bit를 사용
- 메모리는 레지스터와 비교해 사이즈가 크기에 그냥 동작을 시키는것보다 안쓸수 있다면 안쓰는게 더 현명하기 때문에 구지 2bit를 써서 표현
- MemtoReg
- 메모리값을 읽을지 레지스터값을 읽을지(mux 결정)
- MemtoReg는 RegWrite = 0이라면 dontcare(x)가 됨
- ALUOp
- 어떤 사칙연산을 할지
- 4bit가 0000이면 더하기고 0001이면 빼기고 이런건 생략하고 해당 명령어에 어떤 연산이 사용되는지 암기
- ALUSrc
- ALU 연산에 사용될 값을 정함
- rs2값을 읽을지 imm Gen을 통해 만들어진 상수값을 읽을지 정함(mux결정)
- 0이면 rs2, 1이면 imm
- RegWrite
- rd에 값을 쓸 경우 1, 레지스터에 값을 안쓰면 0
- rd를 안쓰는 경우 그냥 0이라 생각하면 됨.
- pc => instruction 제공
- 같은 하드웨어를 사용하기에 특정 명령어에 따른 다른 행동을 할 수 있도록 control signal이 필요
- immGen
- 명령어 내의 immediate를 뽑아내 64bit로 변환(레지스터 크기가 64bit이기 때문에 레지스터값과 연산하려면 64bit가 되어야함, signed expansion을 수행)
- 32bit가 전부 들어가는 이유?
- branch같은 경우 immediate가 여러군데 나뉘어 져 있기에 전부 보냄
alu control으로 2bit 이동 => 4bit
- branch같은 경우 immediate가 여러군데 나뉘어 져 있기에 전부 보냄
R-Type Instruction 동작과정
주 명령어 : add, sub
- immediate는 사용하지 않기에 ALUSrc = 0(rs2 사용)
- ALUOp는 연산에 따라 add or sub or ...
- 메모리 연산은 하지 않기에 MemWrite와 MemRead는 0
- rd에 연산결과 저장 => RegWrite = 1
- MemToReg => 0(메모리 연산값이 아닌 ALU연산 결과를 레지스터에 저장)
Load Instruction 동작 과정(I-Type)
명령어 : Load, addi
Load
- register2부분이 24-20인데 이는 immediate의 일정부분으로 사용하지 않음
- Read register에서 막아버려서 자원을 쓰는것 보다는 그대로 값은 들어오게 하고 뒤에 mux에서 걸러내는것이 더 효율적(막으려면 control signal이 1bit 필요하게 됨)
- ALUSrc = 1 (immediate를 사용)
- ALUOp = +(offset + 상수(상대적 주소))
- MemRead = 1 (메모리 읽어오기 때문)
- MemWrite = 0
- RegWrite = 1(메모리에서 읽은 값을 rd에 저장)
- MemToReg = 1(메모리의 값을 읽어야함.)
addi
- alusrc = 1
- aluop = +
- memread = 0
- memwrite = 0
- regwrite = 1
- memtoreg = 0
Store Insturction(S-Type)
주 명령어 : store
- ALUSrc = 1 (메모리 주소를 구하기위해 상수값과 연산)
- ALUOp = + (offset + 상수(상대적 메모리 주소))
- MemRead = 0 (메모리 읽기는 없음)
- MemWrite = 1 (해당 메모리 주소에 쓰기)
- RegWrite = 0 (레지스터에 값 쓰기 없음)
- 따라서 MemToReg = x(dontcare)
- regwrite = 0(레지스터에 값을 쓰지 않음)
- memtoreg가 0이든 1이든 상관 없이 버려짐 x(dontcare)
- 따라서 MemToReg = x(dontcare)
특이점
- 우선 그림이 조금 잘못된 부분이 있음(Register2가 사용되고 rd(write register가 사용이 안됨))
- store는 rs2를 사용하기에 Read register2 가 사용됨(검정색이여야함)
- ALUSrc는 rs2가 alu에 사용되지는 않고 imm와 rs1의 연산이 이뤄지기 때문에 alusrc=1이여야함.
- rs2는 data memory의 write data로 들어감(ALU연산에서는 쓰이지 않음)
BEQ Instruction
주 명령어 : beq
- ALUSrc : rs1 - rs2 == 0을 이용해 같은지 다른지 체크할 것이기에 rs2가 ALU연산에 사용됨
- ALUOp : - (rs1-rs2 == 0)
- MemRead : 0
- MemWrite : 0
- 메모리 연산x
- RegWrite : 0
- 따라서 MemToReg : x(dontcare)
특이점
- branch문의 경우 상대적주소를 활용한 점프가 사용됨
- 이때 immediate 4:1을 이용해 상대적 점프위치를 표시했음
- 그리고 이 4:1의 경우 실제 값의 1/2배
- +12 -> +6
- 00..00110 = 6 // 6 x 12 + pc
- -20 -> -10
- 00..01010 = 10
- 10의 보수 = 11.110101 + 1 = 11..10110
- 따라서 나머지 immed의 bit는 1이고 뒤의 4bit만 보면 6이라
- 파란색 6으로 표시
- 따라서 실제로 주소값에 더할때는 다시 2배를 해서 더해야함.
- shift left 1 = mul * 2
- 우리가 branch의 상대적 주소를 나타낼때 2배 낮춰서 immediate의 4:1에 저장했었기 때문에 다시 상대적 주소를 찾기 위해 곱하기 2를 해야함
- pc(명령어 주소값) + 상대적 위치값 = branch의 구문 뛰어넘기를 구현 가능
- 이때 immediate 4:1을 이용해 상대적 점프위치를 표시했음
- ALU가 명령어 주소값을 구하는 부분과 register 연산을 하는 부분을 구분하여 나눈 이유
- 조건이 맞는지 틀린지 알게되는 시점에서 주소값들의 연산이 끝나길 기대하기 때문(처리 속도가 올라감)
- rs1-rs2연산이 끝나 같은값인지 아닌지 알게된 시점에 이미 pc+4와 pc+상대적주소값의 연산 결과가 끝나있음
- pc + 4 : 다음주소로 넘어가는 경우 = 4만 더하면 4*8 = 32bit = 명령문 크기 라서 4만 더하면됨
- 처리속도가 올라감
- 조건이 맞는지 틀린지 알게되는 시점에서 주소값들의 연산이 끝나길 기대하기 때문(처리 속도가 올라감)
- branch signal = 0 => 항상 mux가 0임
- branch signal = 1 => alu의 연산 결과에 따라 mux결정
- alu = zero port => alu의 연산결과가 0이라면 1 출력
퍼포먼스 속도
컴퓨터 구조와 성능 개선 방법
1.가장 긴 지연시간이 클럭 주기를 결정
- 그렇게 해야 모든 명령어를 클럭 주기 내에 동작할 수 있어서 작업의 완료가 보장이 됨
- 위에서 배운 명령어 중 Critical Path : Load
- 명령어 메모리 → 레지스터 파일 → ALU → 데이터 메모리 → 레지스터 파일
- 현재 배운 모든 명령어는 기본적으로 아래의 경로를 거침
- pc => instruct memory => register => ALU
- 즉 가장 빠른 명령어 : branch(메모리 연산이 없음)
- 가장 오래 걸리는 명령어 : Load
- load : 400ps
- branch : 100ps
- 라면 최소 clock cycle은 400ps보다 커야함.
- 1/400p Hz의 속도보다 빨라야함
2.서로 다른 명령어에 대해 클럭 주기를 다르게 하는 것은 실행 원칙을 위배
- 1번과 일맥상통
3.공통적으로 발생하는 경우를 빠르게 처리하는 것이 중요
- 로드 명령어는 대부분의 프로그램에서 흔하지 않기 때문에 성능을 높이기 어려움
4.거의 모든 현대의 RISC 프로세서는 파이프라이닝을 통해 성능을 높임
반응형
'컴퓨터 구조' 카테고리의 다른 글
컴퓨터 구조 6(병렬 프로그래밍, GPU&CPU 비교) (0) | 2023.06.28 |
---|---|
컴퓨터 구조 5(캐시) (0) | 2023.06.28 |
컴퓨터 구조 4(파이프라이닝) (0) | 2023.06.28 |
컴퓨터 구조 2(RISC-V) (0) | 2023.05.03 |
컴퓨터 구조 1(구성 요소 및 CPU TIME) (0) | 2023.05.03 |