반응형

전체 datapath 구조

스크린샷 2023-05-02 오후 2 26 49

 

몇가지 살펴볼점

 

  1. pc + 4 연산 Add
    • 명령문 = 32bit = 4byte
    • 따라서 4만 더해주면 다음 명령어를 가리킬 수 있게 되서 4를 더함
  2. Instruction memory와 Data memory
    • 둘다 어떻게 보면 메모리(정확하게는 캐시)인데 둘을 구분하는 이유
      • structure hazard 때문
      • 두 메모리가 합쳐져 있다면 data memory에 접근 시 instruction 메모리에 접근할 수 없기때문에 파이프라이닝이 불가능(5장 내용과 관련)
  3. 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이라 생각하면 됨.
  4. pc => instruction 제공
    • 같은 하드웨어를 사용하기에 특정 명령어에 따른 다른 행동을 할 수 있도록 control signal이 필요
  5. immGen
    • 명령어 내의 immediate를 뽑아내 64bit로 변환(레지스터 크기가 64bit이기 때문에 레지스터값과 연산하려면 64bit가 되어야함, signed expansion을 수행)
    • 32bit가 전부 들어가는 이유?
      • branch같은 경우 immediate가 여러군데 나뉘어 져 있기에 전부 보냄
        alu control으로 2bit 이동 => 4bit

 

R-Type Instruction 동작과정

스크린샷 2023-05-02 오후 2 26 59


주 명령어 : add, sub

  • immediate는 사용하지 않기에 ALUSrc = 0(rs2 사용)
  • ALUOp는 연산에 따라 add or sub or ...
  • 메모리 연산은 하지 않기에 MemWrite와 MemRead는 0
  • rd에 연산결과 저장 => RegWrite = 1
  • MemToReg => 0(메모리 연산값이 아닌 ALU연산 결과를 레지스터에 저장)

Load Instruction 동작 과정(I-Type)

스크린샷 2023-05-02 오후 2 27 11

 

명령어 : 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)

스크린샷 2023-05-02 오후 2 27 17

 

주 명령어 : store

  • ALUSrc = 1 (메모리 주소를 구하기위해 상수값과 연산)
  • ALUOp = + (offset + 상수(상대적 메모리 주소))
  • MemRead = 0 (메모리 읽기는 없음)
  • MemWrite = 1 (해당 메모리 주소에 쓰기)
  • RegWrite = 0 (레지스터에 값 쓰기 없음)
    • 따라서 MemToReg = x(dontcare)
      • regwrite = 0(레지스터에 값을 쓰지 않음)
      • memtoreg가 0이든 1이든 상관 없이 버려짐 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

스크린샷 2023-05-02 오후 2 27 24

 

주 명령어 : 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의 구문 뛰어넘기를 구현 가능
  • 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 프로세서는 파이프라이닝을 통해 성능을 높임

반응형

+ Recent posts