02검증 문제
한계값을 지나치지 않는 카운터
1. 목표와 수정 범위
mkGuardedCounter는 limit에 저장된 값까지 센 뒤 그 값을 유지해야 합니다. 기본 한계는
5입니다. 카운터가 5에 도달하면 atLimit이 참이 되고, setLimit이 다시 호출될 때까지
값과 atLimit이 바뀌지 않아야 합니다.
시작 코드의 카운터는 5에 도달한 뒤에도 한 번 더 증가합니다. 그 결과 atLimit은 한
사이클만 참이었다가 거짓으로 바뀌고, 다시는 참이 되지 않습니다.
수정 대상은 step rule의 준비 조건 하나입니다. 증가식, setLimit, value,
atLimit은 바꾸지 마세요. 이 method들을 고치면 경계 오류가 가려집니다. mkTop은 서버가
고정한 실행 코드이므로 편집하지 않습니다.
2. 실행 코드의 두 구간 읽기
mkTop은 기본 한계 5로 카운터를 실행하다가 cycle 9에서 setLimit(2)를 호출합니다.
cycle 9에는 출력 행이 없습니다. setLimit은 limit과 함께 count도 0으로 예약합니다.
수정된 설계는 실행에서 다음 표와 같은 결과를 보여야 합니다. 실행하기 전에 표의 각 열을 직접 계산해 보세요.
| Cycle | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
value | 0 | 1 | 2 | 3 | 4 | 5 | 5 | 5 | 5 | — | 0 | 1 | 2 | 2 |
atLimit | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | — | 0 | 0 | 1 | 1 |
레지스터 쓰기는 클록 에지에서 반영됩니다. 따라서 cycle 9에 예약된 0은 cycle 10의 출력에서 처음 보입니다.
3. 시작 코드의 경계 오류 예측하기
count == limit인 사이클을 손으로 추적해 보세요.
- 두 값이 같으므로
atLimit은 참입니다. - 시작 코드의 준비 조건은 이 상태에서도 참이므로
step이 실행됩니다. step이 한계보다 1 큰 값을 예약합니다.- 다음 사이클에는 이미 한계를 지난 값이 출력되고
atLimit은 거짓이 됩니다.
카운터는 목표값에 도달하지 못한 것이 아니라, 도달한 뒤 멈추지 못합니다. 증가식이나
reset 동작에는 결함이 없습니다. 수정하기 전 코드를 한 번 실행해, 5 다음 값과 그
사이클의 atLimit이 이 예측과 같은지 확인해 보세요.
4. 최소 수정과 설명
준비 조건의 비교식 하나만 고치세요. 수정한 뒤 다시 실행하고 다음 두 질문에 답해 보세요.
- 카운터가 한계값과 같은 사이클에
step이 실행되지 않는 이유는 무엇일까요? - 비교 경계를 1 작게 또는 1 크게 잡으면 카운터는 각각 어느 값에서 멈출까요?
5. 완료 조건
- 기본 구간에서 5에 도달하고 cycle 5부터 8까지 5를 유지합니다.
- 두 번째 구간은 cycle 10부터 0, 1, 2로 진행하고 2를 유지합니다.
- 각 한계에서
atLimit이 참이 된 뒤 다음setLimit호출 전까지 참을 유지합니다. setLimit은 여전히count를 0으로 되돌립니다.- 0을 포함한 모든 한계에 같은 준비 조건이 적용됩니다. 5와 2만 특수하게 처리해서는 완료가 아닙니다.
6. 단계형 힌트
힌트 1 — 마지막 실행 시점
step이 마지막으로 실행되어야 하는 count 값을 정해 보세요. 그 값과 카운터가
최종적으로 유지해야 하는 값을 비교합니다.
힌트 2 — 경계 포함 여부
현재 비교는 count와 limit이 같은 경우에도 참입니다. 같은 경우를 포함해야 하는지
판단해 보세요.
개념 설명
rule의 준비 조건은 본문이 실행될 수 있는 사이클을 결정합니다. 본문이 조건에서 검사하는
레지스터를 다시 쓰면, 조건의 경계가 하나만 어긋나도 상태 전이가 한 번 더 일어납니다.
7. 추가 실험
제출 코드의 mkTop은 바꾸지 마세요. 대신 두 번째 한계가 3이라고 가정하고 cycle 10
이후의 표를 새로 작성해 보세요. step이 마지막으로 실행되는 사이클과 그때의 count
값을 표시합니다.