배럴 시프터: 13비트 이동을 다섯 번의 선택으로 만드는 법
고정된 3비트 왼쪽 이동은 배선을 옮기면 표현할 수 있다. 그런데 입력마다 0에서 31까지 달라지는 이동량을 한 사이클에 처리하려면 선택 회로가 필요하다. 배럴 시프터는 이 많은 선택을 작은 이동 단계들의 조합으로 만드는 구조다.
이름이 주는 회전 이미지와 달리, shift와 rotate의 규칙은 다르다. shift는 빈자리에 0이나 부호 비트를 넣고, rotate는 빠져나간 비트를 반대쪽으로 보낸다. 여기서는 먼저 일반적인 가변 shift를 생각하자.
13비트를 옮기는 데 필요한 세 선택
32비트 값을 오른쪽으로 13비트 이동하려면 13=8+4+1로 분해할 수 있다. 이동량의 비트에 따라 1, 2, 4, 8, 16비트 이동 여부를 각각 선택하는 다섯 단계가 있으면 0–31의 모든 이동량을 표현할 수 있다.
각 단계는 현재 값을 그대로 통과시키거나 정해진 거리만큼 이동한 배선을 선택한다. 13의 이진 표현 01101에서는 1비트, 4비트, 8비트 이동 단계가 활성화되고 나머지는 그대로 통과한다. 단계 순서가 고정되어 있으므로 선택 제어도 다섯 비트면 된다.
이것이 32개의 완성된 결과 중 하나를 직접 고르는 표현과 다른 점이다. 32비트 폭에서 다섯 단계의 bitwise mux를 그리면 대략 폭에 비례하는 선택 회로가 단계마다 생긴다. 다만 0 채움과 공통 논리, 목표 자원에 따라 최적화되므로 32×5를 실제 netlist의 정확한 mux 개수로 단정해서는 안 된다.
빈 자리에 무엇을 넣을까
8비트 값 10010000을 오른쪽으로 2비트 이동해 보자. logical shift는 높은 두 자리에 0을 넣어 00100100, unsigned 36이 된다. arithmetic shift는 원래 부호 비트 1을 넣어 11100100, signed −28이 된다. 같은 입력 배선과 이동량인데 채움 규칙에 따라 숫자의 의미가 달라진다.
산술 오른쪽 이동을 일반적인 signed 나눗셈으로 오해해서도 안 된다. 음수의 잃는 비트와 반올림 규칙에 따라 2의 거듭제곱으로 나눈 몫의 정의가 다를 수 있다. 하드웨어 명령이나 알고리즘이 요구하는 비트 결과를 기준으로 검증해야 한다.
Ibex ALU의 shift 구현은 이동 방향과 fill 값을 정하고 오른쪽 이동 경로를 구성한다. 왼쪽 shift에는 입력과 출력 비트 순서를 뒤집어 같은 방향의 이동을 재사용하는 관계도 보여 준다. 비트 순서를 뒤집는 것은 각 비트의 숫자 의미를 그대로 유지하는 연산이 아니라 내부 경로를 재사용하기 위한 변환이다.
이동량의 상위 비트를 버려도 되는가
32비트 데이터라는 이유만으로 이동량 32를 어떻게 처리해야 하는지 자동으로 정해지지는 않는다. 인터페이스가 0–31만 허용한다면 다섯 비트로 충분하다. 더 큰 이동량도 받아 모두 0을 내도록 하는 일반 logical shifter라면 큰 값에 대한 처리가 필요하다.
반면 RV32의 기본 register shift처럼 낮은 다섯 비트로 이동량을 정하는 계약에서는 입력 37이 5로 해석된다. Ibex의 해당 경로도 operand_b_i[4:0]를 사용한다. 37을 넣었으니 폭 32보다 크고 결과가 0이어야 한다는 일반 모델은 이 경로의 의미와 다르다.
같은 데이터 폭을 사용하는 두 shifter라도 입력 계약이 다를 수 있다. 상위 이동량 비트를 버린 것이 최적화인지 기능 오류인지는 명령 정의와 모듈 인터페이스를 알아야 판단할 수 있다.
비트 이동이 임계 경로가 되는 이유
다섯 선택 단계는 조합 경로에 이어질 수 있다. 이동량 제어가 늦게 도착하면 마지막 데이터 경로의 결과도 기다린다. 부호 선택, 방향 전환과 결과 mux까지 포함하면 산술 연산을 하지 않는 것처럼 보이는 블록도 중요한 지연을 만들 수 있다.
논리 단계 수를 줄이려고 여러 기능을 크게 병합하면 더 넓은 선택과 fan-out이 생길 수 있다. 반대로 오른쪽 이동 경로를 공유하면 면적을 아낄 여지가 있지만, 방향에 따른 bit reversal과 채움 제어를 결과 경로에 포함해야 한다. 배치·배선과 실제 입력 도착 시간을 함께 보아야 한다.
처리율 요구가 낮으면 이동을 여러 사이클에 나누는 대안도 가능하다. 하지만 한 사이클 shifter와 같은 모듈처럼 연결하려면 latency와 valid의 계약을 바꾸어야 한다. 회로 면적만 줄이고 주변이 같은 사이클 결과를 기대하도록 두면 기능이 달라진다.
잘못 채워진 한 비트를 찾는 입력
검증에서는 모두 0, 모두 1, 최상위나 최하위만 1인 값으로 빠져나가는 자리와 채움 자리를 확인한다. 이동량 0과 최대값, arithmetic shift의 음수·양수를 대조하면 자주 사용하는 중간 이동량만 검사할 때 놓치는 경계를 볼 수 있다.
또 입력의 부호 타입이 올바른지 확인한다. 같은 비트열이어도 언어 표현식이 signed로 해석되지 않으면 의도한 부호 채움이 나오지 않을 수 있다. 수학적 설명, RTL 타입과 명령의 규칙이 같은 shift를 표현해야 한다.
배럴 시프터가 단순 배선이 아닌 이유는 이동 거리가 입력으로 선택되기 때문이다. 핵심은 이동량을 작은 고정 거리들의 선택으로 나누고, 빠져나간 비트와 빈 자리의 의미를 끝까지 보존하는 것이다. 이 관계를 알면 단계 수와 부호 채움, 이동량 제한을 하나의 회로 계약으로 읽을 수 있다.