- 1993년 Intel Pentium은 부동소수점 곱셈을 빠르게 처리하기 위해 3배 값을 만드는 전용 ×3 회로를 포함했고, 이 작은 회로만 수천 개 트랜지스터를 사용함
- Pentium은 64비트 곱셈에서 더할 항을 64개에서 22개로 줄이기 위해 radix-8 곱셈을 쓰지만, 이 방식에서는 ×3 배수를 빠르게 만들어야 함
- ×3 계산 자체는
x + 2x덧셈이지만, 나머지 곱셈 단계가 이 결과를 기다리기 때문에 carry lookahead와 Kogge-Stone 같은 고속 가산기 기법이 필요함 - 회로는 8비트 블록 8개와 상위 lookahead를 결합한 계층형 구조이며, 오버플로와 반올림을 위해 실제 출력은 69비트로 넓어짐
- 약 9000개 트랜지스터가 ×3 회로 하나에 쓰인다는 점은 Pentium 세대에서 성능을 위해 얼마나 복잡한 하드웨어 최적화가 투입됐는지 보여줌
Pentium이 ×3 회로를 따로 둔 이유
- Pentium의 부동소수점 곱셈기는 두 64비트 수를 radix-8 방식으로 곱함
- 일반 이진 곱셈은 각 비트마다 0 또는 피승수를 더하므로 64비트 곱셈에서 64개 항이 필요함
- radix-8 방식은 승수를 3비트씩 묶어 0~7 중 하나를 곱하므로 더할 항이 22개로 줄어듦
- 0~7 배수 중 일부는 하드웨어에서 비교적 간단히 만들 수 있음
- ×2는 1비트 왼쪽 시프트로 처리됨
- ×4는 2비트 왼쪽 시프트로 처리됨
- ×6과 ×7은 Booth 곱셈 알고리듬으로 다음 radix-8 자리의 +1과 현재 자리의 뺄셈을 조합해 처리 가능함
- ×5는 ×8에서 ×3을 빼는 방식으로 얻을 수 있음
- 결국 까다로운 배수는 ×3이며, Pentium은 이를 부동소수점 곱셈기 내부의 전용 회로로 해결함
단순 덧셈이 병목이 되는 지점
- 3배 값은 입력값과 한 비트 왼쪽으로 민 입력값을 더해 만들 수 있음
- 구조만 보면
x + 2x덧셈임
- 구조만 보면
- 병목은 덧셈 과정의 carry 전파에서 생김
- 리플 캐리 가산기는 하위 비트에서 생긴 carry가 상위 비트까지 순차적으로 전달되어야 함
- ×3 결과가 준비되기 전에는 나머지 곱셈 과정이 시작될 수 없어 지연을 줄여야 함
- Pentium은 carry를 순차 전파하지 않고 병렬 계산하기 위해 carry-lookahead adder를 사용함
- 각 비트에서 carry generate와 carry propagate 신호를 만듦
- generate는 해당 위치가 carry를 생성하는 경우를 나타냄
- propagate는 들어온 carry가 밖으로 전달되는 경우를 나타냄
- carry가 병렬로 계산되면 sum 비트도 병렬로 계산 가능함
Kogge-Stone과 2단계 carry lookahead
- carry lookahead를 단순하게 직접 구현하면 비트 수가 커질수록 회로와 배선 부담이 커짐
- 비트 위치가 올라갈수록 논리가 복잡해짐
- 입력이 많은 게이트는 전기적 이유로 느려짐
- Pentium은 8비트 단위의 Kogge-Stone 병렬 프리픽스 가산기를 사용함
- Kogge-Stone은 propagate/generate 신호를 범위 단위로 병합해 carry를 병렬 계산함
- 중간 결과를 재사용해 지연과 회로량을 관리함
- 64비트 전체를 하나의 Kogge-Stone으로 처리하지 않고 2단계 계층 구조로 나눔
- 하위 계층은 8개의 8비트 Kogge-Stone 회로로 각 블록 내부 carry를 계산함
- 상위 계층은 각 8비트 블록을 하나의 단위처럼 보고 블록 간 carry를 계산함
- 두 계층을 결합해 64비트 합에 필요한 carry를 빠르게 제공함
- 회로는 64비트용으로 볼 수 있지만, 실제로는 오버플로 방지와 반올림용 여분 비트를 포함해 69비트 출력을 만듦
carry-select로 기다리는 시간을 줄임
- 각 8비트 블록에는 carry-select adder가 들어감
- carry-in이 0인 경우와 1인 경우의 합을 미리 둘 다 계산함
- 상위 lookahead 회로가 실제 carry-in을 알려주면 멀티플렉서가 올바른 결과를 선택함
- 이 방식은 하드웨어를 더 쓰는 대신 시간을 아낌
- 두 개의 adder와 결과 선택용 멀티플렉서가 필요함
- 합 계산과 carry 계산을 겹쳐 전체 지연을 줄임
- 가장 낮은 8비트 블록은 carry-in이 없어 carry-select 회로가 필요 없음
- 이 블록의 출력 비트는 XNOR 게이트로 계산됨
8비트 블록 안에서 일어나는 일
- ×3 회로의 각 8비트 블록은 입력선을 왼쪽 adder와 오른쪽 경로로 나눔
- 이 분기 구조가 입력값과 한 비트 왼쪽으로 민 입력값을 더해 ×3을 구현함
- 블록 상단은 propagate/generate 신호를 만드는 회로로 구성됨
- 이 신호들은 8비트 Kogge-Stone lookahead 회로로 들어감
- Kogge-Stone 부분은 비트 위치마다 복잡도가 달라 반복 블록처럼 보이지 않고 불규칙하게 보임
- 블록 하단은 carry-select adder 영역임
- 두 합을 미리 계산하고 carry-in에 따라 멀티플렉서가 선택함
- carry-select adder 블록은 주변 회로보다 좁게 배치되어 상위 Kogge-Stone 회로 일부가 들어갈 공간을 만듦
- 각 블록은 출력 비트를 다음 곱셈기 회로로 보내기 전 드라이버 회로로 증폭함
XNOR 게이트와 트랜지스터 수준 구현
- 낮은 비트 영역의 XNOR 게이트는 Pentium에서 멀티플렉서로 구현됨
- Intel 386은 XOR을 AND-NOR 게이트로 구현했고, Z-80은 패스 트랜지스터를 사용했지만 Pentium의 접근은 다름
- 해당 XNOR 회로는 네 개의 인버터와 패스 트랜지스터 멀티플렉서로 구성됨
- 입력 B가 멀티플렉서의 두 입력 중 입력 A 또는 반전된 A를 선택함
- 그 결과 XNOR 함수가 만들어짐
- 칩 사진 분석에서는 상위 두 금속층을 제거해 하단 금속층 M1과 도핑된 실리콘 영역을 관찰함
- 폴리실리콘 선이 도핑 실리콘을 가로지르는 지점이 트랜지스터 게이트가 됨
- CMOS 회로는 위쪽 NMOS와 아래쪽 PMOS 트랜지스터로 구성됨
BiCMOS 출력 드라이버
- ×3 회로의 출력은 높은 전류를 필요로 함
- 각 ×3 신호는 부동소수점 곱셈기 안에서 최대 22개 항을 구동할 수 있음
- 목적지 회로가 ×3 회로에서 멀리 떨어져 있을 수 있음
- 긴 배선과 많은 트랜지스터 게이트 때문에 정전용량이 커지고, 신호를 빠르게 바꾸려면 큰 전류가 필요함
- Pentium은 같은 칩에 bipolar transistor와 CMOS를 결합한 BiCMOS 공정을 사용함
- Pentium은 신호 지연을 최대 35% 줄이기 위해 BiCMOS 회로를 광범위하게 사용함
- Intel은 Pentium Pro, Pentium II, Pentium III, Xeon에도 BiCMOS를 사용함
- 칩 전압이 낮아지면서 bipolar transistor의 이점이 줄어들어 BiCMOS는 결국 사용되지 않게 됨
- ×3 회로의 드라이버는 BiCMOS 드라이버가 다시 두 번째 BiCMOS 드라이버를 구동하는 구조임
- 고전류 인버터의 트랜지스터 게이트가 커서 이를 구동하기 위한 중간 단계가 필요함
- 작은 신호를 여러 단계로 키우면 전체 지연을 줄일 수 있음
- BiCMOS 드라이버의 NPN 트랜지스터는 일반 MOS 트랜지스터와 달리 큰 상자 모양으로 보임
- 인버터는 PMOS로 출력을 높이고 NMOS로 출력을 낮추는 표준 CMOS 구조를 사용함
- 일부 인버터는 강한 high 또는 강한 low 출력을 내도록 비대칭 전류 특성으로 설계됨
곱셈 하드웨어가 보여주는 복잡도 증가
- 컴퓨터 곱셈 하드웨어의 역사는 1950년대까지 거슬러 올라감
- Booth 곱셈 기법은 1951년에 설명됨
- 병렬 곱셈기는 1960년대 중반 Wallace와 Dadda가 제안함
- 초기 마이크로프로세서는 하드웨어 곱셈 지원이 제한적이었음
- 6502 같은 프로세서는 곱셈 하드웨어가 없어 사용자가 시프트와 덧셈으로 소프트웨어 구현을 해야 했음
- Intel 8086은 마이크로코드로 느린 shift-and-add 루프를 수행함
- 386은 multiply unit을 포함했지만 곱셈 명령이 최대 41클록 사이클 걸렸음
- Pentium 시점에는 수백만 개 트랜지스터를 담을 수 있어 더 복잡한 성능 최적화가 가능해짐
- Pentium의 부동소수점 곱셈은 3클록 사이클이 걸리고, 곱셈 회로는 그중 2사이클 동안 사용됨
- 정수 곱셈
MUL은 11사이클로 훨씬 느림 - 2008년 Nehalem 마이크로아키텍처는 부동소수점 곱셈 시간을 1사이클로 줄임
- Pentium의 ×3 곱셈기는 약 9000개 트랜지스터를 포함함
- 이는 1976년 Z80 마이크로프로세서 전체보다 조금 더 많음
- ×3 회로는 Pentium의 부동소수점 유닛 안에 있는 부동소수점 곱셈기의 작은 일부에 불과함