21구현 문제
두 rule 전이의 순서 정하기
1. 문제와 수정 범위
요청 하나는 start, 덧셈, 두 배 연산의 순서로 진행해야 합니다. start 뒤 한 사이클
동안은 seed가 유지됩니다. 다음 원자적 전이에서 increment를 더하고, busy인 중간 상태를
거친 뒤, 둘째 원자적 전이에서 저장된 중간값을 두 배로 만듭니다.
Starter의 addFirst와 doubleSecond는 모두 AddReady에서 활성화됩니다. 두 rule이
valueReg와 phase에 함께 쓰므로 scheduling 충돌이 발생합니다. 하나만 선택된 뒤 즉시
Idle로 돌아가므로, 필요한 연산 하나와 DoubleReady 상태가 사라집니다.
수정 범위는 표시된 phase 결정 두 곳입니다. addFirst가 저장할 다음 phase와
doubleSecond의 guard만 고치세요. 산술식, 인터페이스, start, 별개인 두 rule body는
그대로 둡니다.
2. Starter 읽기와 예측
Starter는 control state에서 시작해 관찰 method 순서로 읽어 보세요.
| 순서 | 선언 | 확인할 내용 |
|---|---|---|
| 1 | Phase | 요청 protocol에 사용할 세 상태 |
| 2 | start | seed와 increment를 저장하고 시작 상태로 전이하는 과정 |
| 3 | 두 rule의 guard와 write set | 동시에 활성화되는 이유와 충돌하는 레지스터 |
| 4 | stage, busy | phase 진행을 외부에서 관찰하는 방법 |
수정하기 전에는 컴파일 단계에서 두 rule의 충돌 경고가 발생해야 합니다. 실행 단계에서는
선택된 rule 하나만 값을 바꾸고 phase가 바로 Idle로 돌아갑니다. 중간
DoubleReady가 관찰되지 않는 현상은 두 전이가 완료되지 않았다는 증상입니다.
3. 상태 전이 복구하기
사용하지 않는 phase를 두 연산 사이의 상태로 쓰세요. 첫 rule은 둘째 연산이 남았음을
표시해야 하고, 둘째 rule은 그 상태에서만 활성화되어야 합니다. 우선순위를 추가하거나 두
산술식을 한 body로 합치면 관찰 가능한 protocol이 달라집니다.
Seed 10과 increment 3의 완료 과정은 다음과 같습니다.
| 관찰 시점 | value | stage | busy |
|---|---|---|---|
start commit 뒤 | 10 | AddReady | 참 |
| 덧셈 전이 뒤 | 13 | DoubleReady | 참 |
| 두 배 전이 뒤 | 26 | Idle | 거짓 |
| 이후 idle 사이클 | 26 | Idle | 거짓 |
반복 요청마다 진입 상태, 중간 상태, 완료 상태가 같은 순서로 관찰되어야 합니다. 새 요청은
Idle에서만 시작합니다. 두 산술 연산은 각각 8비트에서 수행되므로 각 전이에서
순환이 적용됩니다. 넓은 식 하나로 계산한 뒤 마지막에 한 번만 절단해도 최종 8비트 값은
같을 수 있습니다. 그러나 최종값이 같다는 것만으로 별도로 관찰해야 하는 DoubleReady
상태와 그 상태의 8비트 중간값까지 보존되지는 않습니다.
4. 단계형 힌트
힌트 1 — 오류 종류
산술식은 이미 올바릅니다. 세 phase 사이에 필요한 전이를 그린 뒤, 너무 일찍 Idle로
돌아가는 edge를 찾아보세요.
힌트 2 — 사용하지 않는 상태
Starter에서 도달하지 않는 enum label이 하나 있습니다. 이 label로 덧셈은 끝났고 두 배 연산은 남은 상태를 나타낼 수 있습니다.
힌트 3 — 활성 조건 분리
첫 rule은 남은 작업을 나타내는 상태로 전이합니다. 둘째 rule의 guard는 그 상태만
인식해야 하며, AddReady에서는 첫 rule만 활성화되어야 합니다.
5. 추가 실험
수정을 마친 뒤 seed를 8'hfa, increment를 8'h0a로 바꿔 보세요. 실행 전에 덧셈 전이의
8비트 중간값을 계산하고, 저장된 중간값을 두 배로 만든 최종값도 계산해 보세요. 두 전이
사이에서 busy가 참인지도 확인합니다. 추가 실험은 채점 조건이 아닙니다.