모든 이야기

버스 폭을 절반으로 줄일 때 지켜야 할 바이트의 주소

64비트 버스에서 받은 데이터를 32비트 버스로 보내는 회로는 하위 절반과 상위 절반을 차례로 내보내면 끝날 것 같다. AXI width converter에서는 각 비트가 어느 메모리 바이트를 바꾸는지까지 보존해야 한다. 쓰지 않을 바이트를 함께 덮어쓰거나 비정렬 첫 beat의 위치를 잘못 잡으면 데이터 비트의 분할은 정확해도 메모리 결과가 달라진다.

쓰기의 단위는 데이터 버스 전체가 아니라 strobe가 켜진 바이트다. WSTRB의 비트 n은 WDATA의 바이트 lane n에 대응한다. 주소와 크기는 그 beat가 사용할 수 있는 lane을 정하고, strobe는 그중 실제로 쓸 바이트를 고른다. 따라서 변환기가 지켜야 할 핵심 관계는 입력 쪽에서 쓴다고 지정한 각 주소·바이트 값이 출력 쪽에서도 같은 의미로 전달되는 것이다. Arm IHI0022H, A3.4.4 Write strobes·Narrow transfers

먼저 정렬된 일반 메모리 쓰기를 보자. 입력 버스는 64비트, 출력 버스는 32비트다. 입력 요청은 주소 0x1000, AWSIZE=3, AWLEN=0인 한 beat INCR이다. byte lane 0부터 7까지 데이터는 각각 0x10부터 0x17까지이며, WSTRB는 0b10100101이라고 정한다. 메모리의 나머지 바이트는 유지해야 한다.

입력에서 실제 쓰는 바이트
0x1000 ← 0x10   (lane 0)
0x1002 ← 0x12   (lane 2)
0x1005 ← 0x15   (lane 5)
0x1007 ← 0x17   (lane 7)

이를 크기 4바이트, 두 beat INCR 하나로 바꾸면 출력 주소는 0x1000이고 AWSIZE=2, AWLEN=1이다. 첫 beat의 32비트 데이터는 0x13121110이며 WSTRB는 0b0101, WLAST는 0이다. 두 번째 데이터는 0x17161514이며 WSTRB는 0b1010, WLAST는 1이다. 여기서 16진수 표기는 lane 0을 낮은 8비트로 놓은 표현이다.

첫 strobe는 주소 0x1000과 0x1002만 바꾼다. 둘째 strobe는 두 번째 beat의 주소 0x1004를 기준으로 0x1005와 0x1007만 바꾼다. 입력의 네 바이트 쓰기와 출력의 네 바이트 쓰기가 정확히 대응한다. 각 출력 beat의 strobe를 모두 1로 바꾸면 원래 유지해야 할 0x1001, 0x1003, 0x1004, 0x1006까지 덮어쓴다. 입력에서 strobe가 꺼진 데이터 비트를 어떤 값으로 받았든 이 바이트들은 쓰면 안 된다.

입력 beat 하나가 출력 beat 두 개가 되었다고 쓰기 응답도 무조건 두 개가 되는 것은 아니다. 위의 출력은 두 beat짜리 burst 하나이므로 쓰기 응답은 하나다. 반대로 변환 과정에서 한 입력 거래를 여러 출력 burst로 나누면 여러 응답을 받아 입력 쪽의 하나로 모아야 한다. beat 분할과 거래 분할을 구분해서 응답 수를 세어야 한다.

PULP의 공개 axi_dw_downsizer 구현에서도 주소 오프셋에 맞춘 byte lane 이동과 strobe 이동을 함께 수행한다. 출력 beat의 수락을 기준으로 주소와 남은 개수를 갱신하며, 거래를 여러 burst로 나눈 경우의 응답 전달 상태도 따로 둔다. 이는 비트 연결 외에 어떤 상태가 폭 변환기에 필요한지 보여 주는 실제 구현이다. PULP AXI, axi_dw_downsizer의 쓰기 경로

비정렬 시작점에서는 더 주의해야 한다. 같은 64비트 입력 버스에서 주소 0x1003, AWSIZE=3, AWLEN=0인 요청을 생각하자. 첫 beat에서 접근 가능한 바이트는 0x1003부터 정렬 단위 끝인 0x1007까지다. WSTRB=0b11111000이면 이 다섯 바이트를 쓴다. “크기가 8바이트니까 시작 주소부터 8바이트”라고 해석해 0x100A까지 보내면 다른 거래를 만든다. Arm IHI0022H, A3.4.1의 Burst address 수식·Unaligned transfers

가상 변환 결과를 4바이트 크기의 INCR 두 beat로 잡으면 첫 시작 주소는 0x1003이고 첫 strobe는 0b1000이다. 다음 beat는 0x1004이며 strobe는 0b1111이다. 입력 lane 3은 첫 출력 lane 3으로, 입력 lane 4부터 7은 둘째 출력 lane 0부터 3으로 이동한다. 두 전송이 쓰는 주소의 합집합은 여전히 0x1003부터 0x1007까지다. 원래 lane 번호를 그대로 복사하면 뒷부분의 바이트 위치가 맞지 않는다.

일반 메모리를 전제로 한 이 예제를 어떤 주변장치에도 그대로 적용할 수 있는 것은 아니다. 접근 크기와 요청 개수에 의미를 부여하는 장치, exclusive access, 지원하지 않는 burst 종류는 별도 조건을 갖는다. 실제 PULP 구현도 모든 burst 변환을 무조건 지원한다고 주장하지 않는다. 연결하려는 양쪽 인터페이스의 지원 범위와 거래 속성을 확인해야 한다.

마지막으로 출력 쪽이 중간 beat를 받지 못하면 변환기는 아직 전달하지 않은 입력 바이트를 보존해야 한다. 첫 절반만 보낸 뒤 입력을 덮어쓰거나, 출력의 일부 오류 응답을 마지막 성공 응답으로 가려도 입력 거래의 의미가 바뀐다. AXI width converter를 검증할 때는 최종 데이터 워드뿐 아니라 주소별 변경 바이트, 미변경 바이트, beat 수와 마지막 표시, 응답의 대응까지 비교해야 한다. 폭이 달라져도 같은 메모리 쓰기가 남는다는 것을 확인하는 기준이다.

버스 폭을 절반으로 줄일 때 지켜야 할 바이트의 주소 · ariser