본문으로 건너뛰기
code0.HDL

23검증 문제

요청 필드 읽기

1. 의도한 동작과 현재 동작

Request 구조체는 8비트 시작 주소 addr, 4비트 전송 길이 length, 쓰기 여부 write를 각각 이름 있는 필드에 보관합니다. lastAddr는 req.addr에 0 확장한 req.length를 더해야 합니다. 덧셈은 8비트에서 수행되므로 결과가 8'hff를 넘으면 하위 8비트만 남습니다.

starter는 컴파일되지만 요청 전체를 pack한 뒤 하위 8비트를 주소로 간주합니다. 이 구간에는 여러 필드의 비트가 섞여 있습니다. 그래서 주소가 같아도 length나 write가 달라지면 계산에 쓰이는 시작 주소까지 달라집니다.

수정 범위는 시작 주소를 얻는 부분입니다. Request 선언, makeRequest, 두 함수의 시그니처는 그대로 두세요.

2. starter 읽기와 예측

lastAddr보다 구조체 선언과 makeRequest를 먼저 읽어 보세요. 주소가 같을 때 write만 바꾸면 결과가 달라져야 하는지 판단하고, pack(req)의 일부를 잘라 쓰는 방식이 그 판단과 어긋나는 이유를 설명해 보세요.

mkTop은 주소 8'h40, 길이 3, write가 참인 요청을 만들고 addr와 lastAddr를 출력합니다. pack 결과에서는 먼저 선언한 필드가 상위 비트를 차지합니다. 하위 8비트에 어느 필드의 비트가 들어가는지 계산해 starter의 lastAddr를 예측한 뒤 한 번 실행해 보세요.

3. 수정과 실행 결과 해석

저장 위치를 추측하지 말고, 주소를 담도록 선언된 필드를 직접 읽으세요. length의 명시적 0 확장은 그대로 두어 덧셈이 8비트에서 일어나게 합니다.

수정한 뒤 공개 실행의 lastAddr는 16진수 43이어야 합니다. 이 값이 더 이상 write의 영향을 받지 않는 이유를 설명해 보세요. 이어서 length와 write를 각각 바꾼 경우와 8비트 wraparound가 일어나는 경우도 실행해 보세요.

4. 완료 조건

  • 이름 있는 addr와 length 필드로 결과를 계산합니다.
  • write 값은 결과에 영향을 주지 않습니다.
  • 8비트 덧셈의 wraparound를 유지합니다.
  • Request, makeRequest, 두 함수의 시그니처를 변경하지 않습니다.
  • 여러 필드 조합과 8비트 경계에서 동작해야 합니다. 요청 하나의 비트 배치에만 맞추어서는 완료가 아닙니다.

5. 단계형 힌트

힌트 1

점 표기법을 쓰면 비트 위치를 몰라도 필드 이름으로 값을 고를 수 있습니다.

힌트 2

길이는 이미 req.length로 읽고 있습니다. 시작 주소도 같은 방식으로 읽을 수 있습니다.

개념 설명

구조체는 값의 각 부분에 안정적인 이름을 붙입니다. deriving (Bits)로 구조체 전체를 비트로 바꿀 수도 있지만, 그 비트 배치는 저장 방식일 뿐 필드와 로직 사이의 인터페이스가 아닙니다. 필드 이름으로 읽으면 나중에 필드 폭이나 선언 순서가 달라져도 로직의 의도가 유지됩니다.

6. 추가 실험

필드 선언 순서를 바꾸거나 플래그 필드를 하나 추가한다고 가정해 보세요. 필드 이름으로 읽는 코드는 두 경우 모두 그대로 동작합니다. 반면 고정된 비트 구간을 잘라 쓰는 코드는 다시 검토해야 하는데, 그 이유를 설명해 보세요.

개념 다시 보기
준비
Main.bsv