본문으로 건너뛰기
code0.HDL

28검증 문제

done을 내지 않는 카운트다운 고치기

1. 요구 동작

Countdown은 지정한 사이클 수만큼 기다립니다.

에지에서의 입력에지 뒤의 count
load = 1cycles
load = 0, count ≠ 0count - 1
load = 0, count = 00

left는 count를 출력하고, done은 count가 0일 때만 1입니다. 5를 load하면 load 에지 뒤 다섯 번째 에지에서 done이 1이 됩니다. 리셋은 count를 0으로 만들므로 리셋 직후 done은 1입니다.

2. 관찰되는 증상

시작 코드는 컴파일되고 load도 정상이며 처음에는 값이 줄어듭니다. 그러나 5를 load한 뒤 done이 끝내 1이 되지 않습니다. 테스트벤치의 대기 루프는 chiseltest의 idle cycle timeout이 멈출 때까지 계속됩니다.

count가 0에 도달하지 못하는 원인을 찾아 설계를 고치세요. 포트와 공개 테스트벤치는 그대로 둡니다.

3. 실행 전 예측

공개 테스트벤치는 다음 순서로 동작합니다.

  1. timeout을 20 사이클로 설정합니다.
  2. 리셋 직후의 done을 검사합니다.
  3. 5를 load하고, load 에지 직후의 left를 검사합니다.
  4. done이 1이 될 때까지 step하며, step마다 WAIT n left=...를 출력합니다.

테스트벤치는 TimeoutException을 잡아 메시지를 TIMEOUT 줄로 출력합니다. 따라서 어느 경우든 실행은 정상 종료됩니다.

실행하기 전에 올바른 카운트다운이 출력할 WAIT 줄과 DONE 줄의 숫자를 적어 보세요. 그다음 시작 코드를 실행해 비교하세요.

4. 원인 진단

timeout 메시지는 입력값을 바꾸는 poke 없이 20 사이클이 지났다는 사실만 알려 줍니다. 출력을 peek하거나 같은 입력값을 다시 poke해도 이 사이클 수는 초기화되지 않습니다. 카운트다운이 멈춘 원인은 WAIT 줄에 있습니다. left가 처음으로 바뀌지 않는 줄을 찾고, 멈춘 값을 확인하세요. 그 값을 감소 조건에 대입해 보세요.

테스트벤치와 설계 중 어느 쪽이 틀렸는지도 판단해 보세요. 계약에 따르면 done은 count가 0이 될 때 1이 됩니다. timeout을 늘리면 같은 hang이 더 오래 걸릴 뿐입니다.

5. 완료 조건

  • n을 load하면 load 에지 뒤 정확히 n번째 에지에서 done이 1이 됩니다. 작은 값, 1, 최댓값 255에서 모두 같습니다.
  • 0을 load하면 done은 계속 1이고, left는 0 아래로 순환하지 않습니다.
  • load가 감소보다 우선합니다. 세는 도중 다시 load하면 새 값부터 다시 세고, load를 유지하면 매 에지마다 다시 load합니다.
  • done을 한 값 일찍 올리는 방식은 수정이 아닙니다. left 자체가 0이 되어야 합니다.

6. 힌트

힌트 1

WAIT 줄에서 left는 어떤 값에서 멈출까요? 그 값으로 감소 조건을 계산해 보세요.

힌트 2

감소는 count가 아직 0이 아닌 동안 계속되어야 합니다. .elsewhen의 조건을 이 규칙과 비교해 보세요.

개념 설명

timeout은 대기 시간에 상한을 둘 뿐, 대기가 끝나지 않는 이유는 알려 주지 않습니다. 대기 루프에는 기다리는 값의 trace나 검사를 함께 두세요. 그러면 hang이 생겼을 때 설계가 더 진행하지 못한 사이클을 바로 찾을 수 있습니다.

7. 추가 실험

고친 설계에서 timeout을 4로 줄이면 실행이 통과할지 예측해 보세요. 그다음 적절한 timeout이 테스트벤치가 load하는 가장 긴 값에 따라 정해지는 이유를 설명해 보세요.

개념 다시 보기
준비

CheerpJ로 브라우저에서 실행합니다. 첫 실행에는 Java 약 14.5 MB와 JAR 약 47 MB를 내려받습니다. 컴파일에 1분 정도 걸릴 수 있습니다. 라이선스

Main.scala