08구현 문제
워드의 바이트 순서 뒤집기
1. 요구 동작
ByteSwap은 32비트 워드의 바이트 순서를 little-endian과 big-endian 사이에서
변환합니다. 최하위 바이트는 최상위로, 최상위 바이트는 최하위로 이동합니다.
0x11223344는 0x44332211이 됩니다.
시작 코드는 asTypeOf(Vec(4, UInt(8.W)))로 워드를 바이트 네 개로 읽습니다. 그러나 같은
Vec을 그대로 다시 묶으므로 모든 워드가 변하지 않고 출력됩니다.
bytes 선언은 그대로 두고 TODO 줄의 연결만 바꾸세요. 두 포트는 32비트를 유지합니다.
2. Vec 원소의 위치
Vec을 asUInt로 묶으면 원소 0이 최하위 비트에 놓입니다. asTypeOf는 같은 배치를
반대로 적용하므로, 평탄한 값의 최하위 바이트가 원소 0이 됩니다.
| 원소 | 0x11223344에서의 값 |
|---|---|
bytes(0) | 0x44 |
bytes(3) | 0x11 |
같은 배치로 풀고 다시 묶으면 항상 원래 값이 됩니다. 그래서 시작 코드는 입력을 그대로 출력합니다.
3. 실행 전 예측
공개 실행은 11223344, 000000ff, deadbeef 세 워드를 출력합니다. 각 워드의 바이트
순서를 뒤집은 값을 먼저 적어 보세요. 그다음 시작 코드가 입력을 그대로 출력하는지 확인하세요.
4. 실행 결과 해석
올바른 설계는 44332211, ff000000, efbeadde를 출력합니다. 순서를 뒤집으려면 원소
0이 최상위에 놓이는 순서로 묶어야 합니다. deadbeef는 바이트 단위로 뒤집히며, ef 안의
두 16진수 자리는 순서를 유지합니다.
5. 완료 조건
- 모든 32비트 워드에서 바이트 0과 3, 바이트 1과 2가 서로 위치를 바꿉니다.
- 입력의 어느 위치에 있는 1비트든 대칭 위치의 바이트로 이동하며, 바이트 안의 위치는 유지됩니다.
- 16비트 절반 두 개를 맞바꾸는 연산은 다른 연산이므로 완료로 인정되지 않습니다.
6. 단계형 힌트
힌트 1
두 묶기 규칙은 방향이 반대입니다. Vec의 asUInt는 원소 0을 최하위에 두고, Cat은
첫 번째 인자를 최상위에 둡니다.
힌트 2
Vec은 elaboration 중에 Scala 시퀀스로도 사용할 수 있습니다. Scala 컬렉션 메서드로
원소 순서를 바꾼 뒤 VecInit으로 다시 하드웨어 Vec을 만들 수 있습니다. Cat에 네
바이트를 직접 나열해도 됩니다. 이때는 chisel3.util._을 들여와야 합니다.
개념 설명
asTypeOf와 asUInt는 하나의 고정된 배치를 양방향으로 적용합니다. 바이트 순서는
elaboration 중에 원소를 재배치해서 바꾸며, 이 재배치는 배선일 뿐 논리를 추가하지
않습니다.
7. 추가 실험
별도 사본에서 bytes의 타입을 Vec(2, UInt(16.W))로 바꾸고 같은 방식으로 뒤집어 보세요.
11223344의 출력을 예측하고, 결과가 바이트 교환이 아니라 16비트 단위 교환이 되는 이유를
설명해 보세요.