본문으로 건너뛰기
code0.HDL

03구현 문제

누적과 전달을 두 단계로 나누기

1. 목표와 수정 범위

mkRuleOrder는 1, 2, 3, 4를 accumulator에 더한 뒤 완성된 합 10을 result로 정확히 한 번 옮겨야 합니다. 수집은 fill rule이, 전달은 drain rule이 맡습니다.

수정 대상은 TODO 아래 drain의 준비 조건 하나입니다. 두 rule의 본문, 레지스터 선언, method, mkTop은 그대로 두세요. 우선순위 어트리뷰트나 새 레지스터도 추가하지 않습니다.

2. 시작 코드 읽기

mkRuleOrder의 레지스터 다섯 개는 다음 역할을 합니다.

레지스터역할
accumulator아직 전달하지 않은 누적값
resultemitted method가 반환하는 값
taken다음에 더할 항을 고르는 순번
collecting수집 단계이면 참
drained전달을 이미 했으면 참

시작 코드에서 fill과 drain의 준비 조건은 똑같이 collecting입니다. 두 rule은 같은 사이클에 함께 활성화됩니다. 두 rule 모두 accumulator를 읽고 쓰므로, 어느 쪽을 먼저 배치해도 다른 쪽의 읽기가 쓰기 뒤에 놓입니다. 따라서 같은 사이클에 함께 실행될 수 없습니다. 실행의 컴파일 단계에서는 fill을 우선 처리했다는 G0010 경고와, 생성된 schedule에서 drain이 실행될 수 없다는 G0021 경고가 출력됩니다.

3. 수정 전 결과 예측하기

실행하기 전에 다음 표를 예측하고, 수정 전 코드를 한 번 실행해 비교해 보세요.

Cycletotalemittedfilling상태
00011을 더할 차례
11012를 더할 차례
23013을 더할 차례
36014를 더하고 수집 종료
41000합은 완성됐지만 전달되지 않음
5 이후1000상태 변화 없음

사이클을 더 기다려도 10은 전달되지 않습니다. collecting이 거짓이 되면 시작 코드의 두 준비 조건이 모두 거짓이 되기 때문입니다.

4. 단계 전환을 조건으로 표현하기

accumulator를 쓰는 시점을 두 단계로 나누세요. 수집 중에는 fill만 실행되고, 수집이 끝난 뒤에는 drain이 정확히 한 번 실행되어야 합니다.

drain의 준비 조건은 기존 상태로 두 사실을 함께 확인해야 합니다. 하나는 수집 단계가 끝났다는 사실이고, 다른 하나는 전달 기회가 아직 남아 있다는 사실입니다. 각 사실에 해당하는 레지스터가 그때 가져야 할 Boolean 값을 먼저 정한 뒤 조건식을 작성해 보세요. 채점은 조건식의 표기가 아니라 관찰되는 동작을 확인하므로 동등한 조건식도 허용됩니다.

5. 수정 후 실행 결과 해석하기

수정한 코드를 실행하고 cycle 4와 5를 확인해 보세요.

  • cycle 4에서는 네 번째 덧셈이 반영되어 total이 10이고 filling이 0입니다.
  • 이 사이클에 drain이 10을 result에, 0을 accumulator에 예약합니다.
  • 예약된 쓰기는 클록 에지에서 반영됩니다. 따라서 cycle 5에는 total이 0, emitted가 10으로 출력됩니다.
  • drained가 참이 되므로 이후 drain은 다시 실행되지 않습니다. 빈 누적값 0이 이미 전달한 10을 덮어쓰지 않습니다.

두 rule이 더 이상 accumulator를 두고 충돌하지 않는 이유와, drain이 완성된 합을 읽는 이유를 직접 설명해 보세요.

6. 완료 조건

  • 누적값은 0, 1, 3, 6, 10 순서로 변합니다.
  • 수집 중에는 drain이 실행되지 않습니다.
  • 수집이 끝난 뒤 전달은 한 번만 일어납니다.
  • 전달 뒤 total은 0, emitted는 10입니다.
  • 이후 사이클에서도 emitted는 10을 유지합니다.

7. 단계형 힌트

힌트 1 — 단계 구분

drain은 fill이 실행되는 단계와 반대인 단계에서만 준비되어야 합니다.

힌트 2 — 한 번만 전달

반대 단계만 검사하면 전달이 여러 번 일어날 수 있습니다. 전달을 이미 했는지 기록하는 레지스터도 함께 검사하세요.

개념 설명

컴파일러는 각 rule의 조건과 읽고 쓰는 상태로 schedule을 만듭니다. 두 rule이 서로 상대가 쓰는 값을 읽으면 충돌하고, 한쪽은 그 사이클에서 제외됩니다. 같은 레지스터에 쓰기만 하는 두 rule은 함께 실행될 수 있으며, schedule 순서가 뒤인 쓰기가 남고 bsc가 덮인 쓰기를 경고합니다. 두 조건이 동시에 참이 될 수 없으면 충돌도 사라집니다.

8. 추가 실험

필수 수정을 확인한 뒤 accumulator의 초기값을 8로 바꾼다고 가정해 보세요. 누적값은 8, 9, 11, 14, 18로 변하고, 전달 뒤에는 total이 0, emitted가 18이어야 합니다. 이 실험으로 구현이 10을 고정해서 내보내지 않고 실제 누적값을 전달하는지 확인할 수 있습니다.

개념 다시 보기
준비
Main.bsv