13검증 문제
리셋에서 sticky 플래그 지우기
1. 요구 동작
ErrorMonitor의 seen은 sticky 플래그입니다. 첫 오류가 들어온 다음 사이클에 1이 되고,
다음 리셋 전까지 0으로 돌아가지 않습니다. errors는 오류 사이클 수를 16으로 나눈
나머지로 셉니다. errors가 16번째 오류에서 0으로 돌아가도 seen은 1을 유지합니다.
리셋은 두 출력을 모두 0으로 만듭니다. 리셋 직후 아직 오류가 없으면 seen은 0입니다.
2. 관찰되는 증상
시작 코드는 컴파일되고 errors도 올바르게 셉니다. 결함은 seen에 있습니다. 오류가 한 번
들어온 뒤 리셋하면 errors만 0이 되고 seen은 1로 남습니다. 첫 오류 전의 seen
값이 0이라는 보장도 없습니다.
두 레지스터가 같은 리셋에 다르게 반응하는 원인을 찾아, seen이 계약을 따르도록
고치세요. 포트와 카운터는 그대로 둡니다.
3. 실행 전 예측
공개 테스트벤치는 다섯 시점의 값을 출력합니다.
| 출력 이름 | 시점 |
|---|---|
start | 첫 입력 전 |
after-errors | 오류 두 사이클과 오류 없는 한 사이클 뒤 |
after-reset | 리셋 에지 한 번 뒤 |
quiet | 그다음 오류 없는 한 사이클 뒤 |
new-error | 새 오류 한 사이클 뒤 |
올바른 모니터의 seen과 errors 두 열을 먼저 적어 보세요. 그다음 시작 코드를 실행해,
리셋이 일어났는지에 대해 두 열이 서로 다른 값을 보이는 줄을 찾아보세요.
4. 원인 진단
리셋은 리셋 값을 선언한 레지스터에만 적용됩니다. 두 레지스터는 모두 when(io.err)
안에서 갱신되므로 다음 값 로직의 구조는 같습니다. 따라서 리셋에 대한 반응 차이는
레지스터를 만든 방식에서 생깁니다. after-reset 줄을 근거로 두 선언 가운데 어느 쪽에
리셋 값이 없는지 판단해 보세요.
주의. 시작 코드의 start 줄도 신뢰할 수 있는 값이 아닙니다. 리셋 값이 없는
레지스터는 시작 상태가 정의되지 않습니다.
5. 수정 후 확인
결함이 있는 선언만 고치고 다시 실행하세요. after-reset 줄의 두 열은 모두 0이어야
하고, new-error 줄에서는 플래그가 다시 1이 되고 카운트는 1이어야 합니다. 수정 후
start 줄이 우연히 맞은 값이 아니라 보장된 값이 되는 이유를 설명해 보세요.
6. 완료 조건
- 리셋 직후 오류가 없으면
seen은 0입니다. - 첫 오류 뒤
seen이 1이 되고, 오류 없는 사이클과 카운터의 wraparound 동안 유지됩니다. - 리셋하면
seen과errors가 함께 0이 됩니다.err가 1인 사이클에 리셋이 걸려도 같습니다. seen을errors에서 계산하는 방식은 수정이 아닙니다. 오류가 16번 들어오면 카운터는 0이 되지만 플래그는 1을 유지해야 합니다.
7. 힌트
힌트 1
seen과 errors를 만드는 생성자를 비교해 보세요. 초기값을 받는 생성자는 하나뿐입니다.
힌트 2
순차 회로 장의 리셋 표를 보면 Reg로 만든 레지스터는 리셋 에지를 지나도 값을
유지합니다. seen을 리셋 값 false를 받는 생성자로 만드세요.
개념 설명
리셋은 회로 전체를 지우는 신호가 아니라 레지스터 선언마다 정하는 속성입니다. valid 비트, 플래그, 카운터처럼 시작 상태가 정확성을 결정하는 제어 상태에는 리셋 값이 필요합니다. 사용 전에 항상 새 값을 쓰는 데이터 레지스터는 리셋을 생략할 수 있습니다.
8. 추가 실험
errors도 리셋 값 없이 선언되었다고 가정해 보세요. after-reset 줄을 예측하고, 이
경우 두 열을 비교하는 방법으로는 결함을 드러낼 수 없는 이유를 설명해 보세요.