[CSAPP] Y86-64 ISA의 순차적 구현: SEQ 프로세서 동작 원리 분석

1. 문제 제기 (Introduction & Problem Statement)

  • 관찰 현상 또는 질문:
    복잡한 상용 프로세서의 ISA(Instruction Set Architecture)인 x86-64는 어떻게 하드웨어로 구현될까? 이 근본적인 질문에 답하기 위해, x86-64의 핵심 기능만 간추린 교육용 ISA, Y86-64를 통해 가상 CPU의 동작 원리를 탐구한다.

  • 탐구 목표:
    본 아티클에서는 Y86-64 ISA의 정의와 이를 하드웨어로 구현하는 데 필요한 디지털 논리의 기본 개념을 학습한다. 최종적으로, Y86-64 명령어를 한 클럭 사이클에 순차적으로 처리하는 SEQ 프로세서의 6단계(인출, 해독, 실행, 메모리, 쓰기, PC 업데이트) 동작 원리를 분석하여 프로세서의 가장 기본적인 구현 방식을 이해하는 것을 목표로 한다.


2. 기술 분석 및 핵심 원리 (Technical Deep Dive)

2-1. Y86-64 ISA와 디지털 논리 기초

본격적인 분석에 앞서, Y86-64 아키텍처와 이를 구현하는 데 사용되는 하드웨어 언어의 기본 개념을 정의한다.

  • Y86-64 ISA (Instruction Set Architecture): x86-64의 핵심 부분만 간추린 단순화된 교육용 ISA이다. 실제 하드웨어 구현(마이크로아키텍처)의 원리를 학습하기 위해 설계되었다.
  • 프로그램 가시 상태 (Programmer-Visible State): Y86-64 프로그램이 접근하고 변경할 수 있는 프로세서의 상태를 의미한다.
    • 레지스터: 15개의 64비트 범용 레지스터가 있다.
    • PC (Program Counter): 다음에 실행할 명령어의 주소를 저장한다.
    • 조건 코드 (CC): 연산 결과의 상태를 나타내는 1비트 플래그 (ZF, SF, OF)이다.
    • 프로그램 상태 (Stat): 프로그램 실행 상태(정상, 오류 등)를 나타낸다.
    • 메모리 (DMEM): 프로그램의 코드와 데이터를 저장하는 거대한 바이트 배열이다.
  • 명령어 인코딩: 모든 Y86-64 명령어의 첫 바이트는 명령어 종류를 나타내는 코드(상위 4비트)와 세부 동작을 지정하는 함수(하위 4비트)로 구성된다.
  • HCL (Hardware Control Language): 디지털 논리 설계를 표현하기 위한 언어이다. AND(&&), OR(||), NOT(!)과 같은 기본 논리 연산으로 조합 회로를 기술한다.
  • 조합 회로: 출력이 오직 현재 입력에 의해서만 결정되는 논리 회로이다. 대표적으로 여러 입력 중 하나를 선택하는 멀티플렉서(MUX)가 있다. HCL에서는 케이스 표현식으로 이를 구현한다.
  • 순차 회로: 상태를 저장할 수 있는 회로로, 클럭 신호에 동기화되어 상태를 업데이트하는 레지스터를 포함한다. 프로세서는 레지스터의 현재 상태를 읽고, 조합 논리를 거쳐 다음 상태에 쓸 값을 계산하는 방식으로 동작한다.
  • 클럭 (Clock): 디지털 시스템이 동작의 박자를 맞추기 위해 사용하는 주기적인 전기 신호이다. 클럭 신호가 0에서 1로 변하는 '상승 에지' 순간에 레지스터의 값이 업데이트되며, 클럭 속도(예: 3.5GHz)는 1초당 이 주기가 반복되는 횟수를 의미한다.

2-2. SEQ 프로세서의 순차적 구현 및 동작 단계

SEQ는 Y86-64 ISA를 구현한 가장 단순한 순차 처리 프로세서이다. 핵심 특징은 한 클럭 사이클 동안 단 하나의 명령어를 처음부터 끝까지 처리한다는 점이다. 이 과정은 6개의 단계로 나뉜다.

  • 1단계: 인출 (Fetch)

    • PC가 가리키는 메모리 주소에서 명령어(1~10바이트)를 읽는다.
    • 첫 바이트를 분석하여 명령어 코드(icode)와 함수(ifun)를 분리한다.
    • 필요한 경우 추가 레지스터 지정자 바이트나 상수 값을 읽어온다.
      ...
    • 다음 명령어 주소(valP)를 계산한다. (valP = 현재 PC + 읽어온 명령어 길이)
  • 2단계: 해독 (Decode)

    • 실행에 필요한 피연산자를 레지스터 파일에서 읽어온다.
    • 인출 단계에서 파악한 레지스터 ID를 사용하여 valA, valB와 같은 값을 준비한다.
    • 스택 포인터(%rsp)를 사용하는 명령어의 경우, 스택 포인터 값을 읽어온다.
  • 3단계: 실행 (Execute)

    • 산술/논리 연산(ALU)을 수행하거나 유효 주소를 계산한다.
    • ALU는 ifun 값에 따라 덧셈, 뺄셈 등의 연산을 수행하고 결과를 valE에 저장한다.
    • 메모리 접근 명령어의 경우, 베이스 레지스터와 오프셋을 더해 유효 메모리 주소를 계산한다.
    • 이 단계에서 연산 결과에 따라 조건 코드(CC)가 설정될 수 있다.
  • 4단계: 메모리 (Memory)

    • 데이터를 메모리에서 읽거나 메모리에 쓴다.
    • 실행 단계에서 계산된 주소를 사용하여 DMEM에 접근한다.
  • 5단계: 쓰기 (Write-back)

    • 실행 단계의 결과(valE) 또는 메모리 단계에서 읽은 값(valM)을 레지스터 파일에 쓴다.
  • 6단계: PC 업데이트 (PC Update)

    • 다음 클럭 사이클을 위해 PC 값을 새로운 주소로 업데이트한다.
    • 기본적으로는 인출 단계에서 계산한 valP로 업데이트되지만, 분기 명령어의 경우 조건에 따라 다른 주소로 변경된다.

SEQ의 핵심은 하나의 긴 클럭 사이클 동안, 위의 모든 단계가 안정적으로 완료될 수 있도록 충분한 시간을 보장하는 것이다.


3. 결론 및 고찰

  • 핵심 요약:

    • Y86-64는 복잡한 x86-64의 원리를 이해하기 위해 설계된 교육용 ISA이다.
    • SEQ 프로세서는 Y86-64 명령어를 '인출-해독-실행-메모리-쓰기-PC 업데이트'의 6단계로 나누어 하나의 긴 클럭 사이클 동안 순차적으로 처리하는 가장 단순한 프로세서 구현체이다.
  • 기술적 통찰 및 나의 생각:
    이번 학습을 통해 ISA가 소프트웨어와 하드웨어 간의 '무엇을 할 것인가'에 대한 약속이라면, SEQ와 같은 마이크로아키텍처는 '어떻게 할 것인가'를 구체적인 하드웨어 단계로 구현한 것임을 명확히 이해했다. 특히, 클럭이라는 박자에 맞춰 명령어의 인출부터 결과 저장까지 모든 단계가 순차적으로 일어나는 모습은 추상적인 개념이었던 프로세서의 동작을 구체적으로 그려볼 수 있게 했다. SEQ는 가장 단순한 구현이지만, 모든 현대 프로세서 설계의 기본이 되는 핵심 원리라는 점을 깨달았다.

  • 향후 과제 / 추가 질문:
    SEQ 모델은 한 클럭에 하나의 명령어만 처리하여 자원이 낭비되고 성능이 낮다. 다음 단계로, 여러 명령어를 동시에 다른 단계에서 처리하여 성능을 극적으로 높이는 파이프라인(Pipelining) 기법의 원리와, 이를 적용한 PIPE 프로세서의 구조는 SEQ와 어떻게 다른지 탐구해보고 싶다.


4. 참고 자료

  • [책] Computer Systems: A Programmer's Perspective (CSAPP) - 4장 프로세서 아키텍처