Computer Science/Computer Architecture

[Computer Architecture] Instructions: Language of the computer - 1

LeeJaeJun 2024. 2. 6. 12:07
728x90
반응형

Registers

  • 프로세서 안에 들어있는 하드웨어 구성 요소임
    • CPU를 만들고나서, 사용가능한 레지스터의 개수를 바꾸지 못하는 이유임
  • RISC-V 아키텍쳐에서는 32개의 integer 레지스터 이용 가능
    • 0부터 31번까지 이름 붙여져 있음
    • x0-x31
    • 어셈블리에서 이름 사용 가능
  • 32-bits wide
  • x0 레지스터는 항상 0임
    • x0에 다른 값을 쓰려고하면 무시됨
  • Instruction architecture를 정의할 때, architecture가 제공하는 register를 먼저 정의해야 함

RISC-V registers

 

Two's complement operations

  • Negate: 모든 bit를 invert하고 1을 더함
  • 더 큰 bit 형태로 나타내는 법
    • RISC-V에서는 the most significant bit(the sign bit)를 채우는 방식 사용

 

RISC-V arithmetic

  • 모든 instruction은 3개의 operand로 이루어져 있음
  • operand의 순서는 고정되어 있음
    • arithmetic instruction의 경우, destination이 항상 먼저 온다
  • 더 많은 operand를 제공하지 않는 이유는 Instruction이 복잡해지지 않게 하기 위해서임

x1 = a, x2 = b, x3 = c

  • Design principle
    • simplicity favors regularity
      • Regularity는 실행을 더 간단하게 만듦 -> 하드웨어를 simple하게 만들 수 있음
      • Simplicity는 낮은 비용으로 높은 성과를 가능하게 함
      • Arithmetic 연산에서 operand는 register만 가능(memory는 안됨)
      • 각 register는 32bit
    • smaller is faster
      • 레지스터가 더 많으면 더 많은 회로를 지나야하기 때문에 clock cycle time을 증가시켜서 더 느려질 수 있음 -> 레지스터 개수를 많이 안늘리는 이유
      • 레지스터를 32(2^5)개보다 더 적게 하면 프로그램에서 사용하는 변수들을 모두 다 레지스터에 매핑할 수 없기에 더도말고 덜도말고 딱 32개를 씀
      • 레지스터에 저장할 수 없으면 변수들을 메모리에 저장해야하는데 그렇게하면 성능이 떨어짐
    • Make the common case fast
      • 작은 constants(상수)들은 자주 쓰임 -> 사용할 가능성이 높은 상수들을 레지스터에 미리 하드웨어화 시킴
      • 자주 쓰이는 것들이 메모리에 들어가 있으면 load instruction을 계속 사용해야해서 성능이 느려짐
      • RISC-V Instruction
        • Immediate operand 사용: operand에 레지스터가 아니라 하드웨어화 시켜 놓은 숫자를 사용
          • Ex) add라는 32bit 명령어 안에 이미 상수값이 들어가 있어서 명령어를 fetch하면 그 안에 이미 값이 들어가 있어서 바로 연산 가능 -> 메모리로부터 load를 안해도 되기에 성능 향상
        • 빼기 연산 같은 경우에는 instruction이 없음
          • 빼기를 하는 것이 아니라 음수를 더하는 방식으로 사용
          • 비슷하게 branch 도 blt(branch if less than)과 bge(branch if greater than or equal)은 있지만 bgt나 ble는 없음(argument 순서를 바꿔서 사용하면 되니까)
        • 0번 레지스터는 항상 상수 0을 나타냄
          • 0은 굉장히 많이 사용되기에 아예 Register에 고정시켜놓음
      • 큰 상수의 경우에는 lui와 addi라는 Instruction을 조합하여 load upper immediate instruction 구현

 

  • Instruction 안에 constant 값을 적어주는 것은 32bit 명령어 안에 일부 자리를 할당하는 방식이기에 다른 정보도 담아야하여 많은 자리를 주지는 못함 -> 큰 숫자는 담을 수 없음
  • 그래서 bit를 shift하는 방식을 활용해서 값을 저장함
  • ex) addi는 imm에 해당하는 bit가 12개 밖에 안됨. lui연산은 20bit의 Input immediate값을 받고 그 값을 상위 20bit에 위치시킴. lui을 활용해서 rd의 31번째부터 12번째까지를 위치시키고 남은 12비트는 0의로 채운 다음에 그 남은 12비트에 addi를 덧셈하여 32bit짜리를 큰 수를 완성시킬 수 있음
  • Pseudo-instruction은 가짜 instruction을 의미
    • assembly code에서만 사용 가능
    • 사용자의 편리성을 위해서 존재
    • ex) li라는 pseudo instruction을 쓰면 내부적으로는 lui와 addi를 이용해서 동작함

 

Memory organization

  • 주소를 가진 큰 1차원 배열이라고 생각
  • Arrays, structures, dynamic data 등 composite data들을 위해 사용
  • arithmetic operations을 위해서 메모리에서부터 데이터를 레지스터로 가져오고, 데이터를 arithmetic 연산 장치에 보내고 연산하고, 다시 memory에 그 값을 저장하는 방식 사용
  • 메모리 주소는 array의 index라고 생각
  • Byte addressing -> 1개의 Index가 1byte를 나타내는 주소 체계
  • 실제로는 대부분 데이터는 word 단위를 사용하기 때문에 32bit architecture에서는 word 단위(32bit, 4 bytes)로 인덱싱하여 사용
  • 2^32 bytes는 bytes address 0부터 2^32-1 사용
  • 2^30 words는 byte address 0, 4, 8, ... 2^32-4 사용
  • Words are aligned
    • word의 주소는 word 사이즈인 4byte의 배수로 되어 있음
    • word 주소 체계에서는 주소를 bit 단위로 나타냈을 때 마지막 두 비트는 의미가 없음
      • 4의 배수이기 때문에 마지막 2 bit는 항상 00 이기 때문


Alignment(정렬)

  • 각 object(data)가 그것의 사이즈의 배수에 해당하는 곳에 위치하고 있을 때 정렬되어 있다고 함
  • 성능에 큰 영향을 줌
    • alignment가 되어있다면 성능이 빠르지만, 그렇지 않다면 성능이 떨어짐

 

 

Byte ordering

  • Endian: 컴퓨터 메모리와 같은 1차원 공간에 여러 개의 연속된 대상을 배열하는 방법
    • Big Endian: Most significant byte를 먼저 배치
    • Little Endian: Least significant byte를 먼저 배치
  • 일종의 convention으로 big endian이나 little endian은 성능은 동일함 (type이 다를 뿐)
  • RISC-V는 little endian 사용

 

Registers vs Memory

  • Arithmetic instructions operands는 레지스터에 있음(메모리 주소를 operand로 줄 수 없음)
    • only 32 registers provided
  • 컴파일러는 레지스터에 변수를 연결 -> 컴파일러가 어떻게 변수를 mapping하는 지가 성능에 영향
  • 레지스터는 메모리보다 접근하는데 속도가 빠름
  • 메모리 데이터에 대한 작동은 load와 store이 필요하기 때문에 많은 instruction이 실행되어야 함
  • 레지스터에 올라와 있는 데이터 중 잘 안쓰는 것은 메모리에 보내버리고 나중에 필요할 때 다시 읽어오는 식으로 작동
    • 제한된 개수의 레지스터를 가지고 돌아가면서 사용
    • 계산해놓은 값은 메모리에 저장했다가 나중에 사용할 때 다시 읽어오는 방식
  • 성능을 높이기 위해서는 레지스터를 얼마나 효율적으로 사용하는지가 중요

 

RISC-V memory

* Store는 arithmetic instruction이 아님.

 

Sign-extension vs Zero-extension

  • 만약 데이터가 8bit여도 레지스터가 32bit이기 때문에 32bit로 확장되어야 함
  • signed이면 첫 번째 bit를 기준으로 채우고, unsigned라면 0으로 채움

 

Branch

  • 2's complement range: [-2^n-1, 2^n-1 -1]
  • PC-relative addressing tㅏ용
    • 절대값이 따로 있는 것이 아니라 그 주소를 기준으로 +-2^11 byte 안의 범위에서 이동 가능
    • Instruction은 4 byte이기 때문에, 현재 instruction 기준으로는 +-2^9 범위 안의 instructions으로 이동 가능
  • 이 두 비트 값을 저장하지 않고 당연히 2비트라고 생각하고 계산하면 더 많은 범위를 이동 가능word 단위로 이동하기 때문에 instruction의 마지막 2비트는 항상 00임

  • (PC + immediate)는 3개의 Instruction 또는 12 byte를 이동
  • 정리하자면, 현재 PC를 기준으로 +-2^11 instructions(+-2^13 bytes)를 이동할 수 있음
  • RISC-V에서는 16-bit comprressed instruction과 16bit의 배수의 길이의 variable-length instructions의 extension을 지원함
    • 16-bit encoding 또한 지원해야 하기에, 마지막 2비트를 다 버리면 안됨. 1bit만 버릴 수 있음(마지막 1개 bit만 0이라고 가정하고 계산)
    • 그래서 +-2^10 32-bit instructions(+-2^12 bytes) 범위 내에서만의 이동을 지원함
    • C-extension 같은 경우에는 4byte아니라 2byte 기준으로 구분짓는데, 마지막 2bit를 버리면 이와도 호환이 안됨
      • 그래서 [13:2]를 사용하는 것이 아니라 [12:1]를 사용해서 1개만 버리는 방식을 채택
728x90
반응형