writeback 중재: 다른 사이클에 보낸 두 결과가 함께 돌아올 때
실행 장치를 두 개 붙였는데 결과를 쓰는 포트는 하나뿐이라고 하자. 두 장치가 같은 사이클에 끝나면 둘 다 계산을 올바르게 했어도 결과 하나를 잃을 수 있다. writeback 중재는 계산을 더 빨리 하는 문제가 아니라, 완성된 결과를 언제 어떤 경로로 받아들일지 정하는 문제다.
issue 충돌을 피했어도 완료가 겹친다
가상의 코어는 한 사이클에 명령 하나만 보내고, 두 연산 장치의 결과는 같은 쓰기 포트를 사용한다. 여기서 지연 L은 issue 사이클 번호에 L을 더한 사이클에 결과가 쓰기 포트에 도착한다는 뜻으로 정의한다.
명령 P: 사이클 1에 issue, 지연 3 → 사이클 4에 결과
명령 Q: 사이클 3에 issue, 지연 1 → 사이클 4에 결과
서로 다른 사이클에 보냈지만 도착은 겹친다. 한 번에 결과 하나만 받는 포트라면 어느 것을 먼저 쓸지 정하고 다른 결과를 보관해야 한다. “각 장치가 바쁘지 않았을 때 보냈다”는 조건만으로 미래의 쓰기 포트 충돌이 사라지지는 않는다.
고정 지연 연산만 있고 도착 시점을 정확히 안다면, 보내기 전에 완료 사이클을 예약하는 선택이 가능하다. 또는 같은 issue 흐름의 연산 지연을 모두 3으로 맞추면 P는 4, Q는 6에 도착한다. 이 예에서는 issue 간격이 완료 간격으로 그대로 옮겨져 충돌이 없다. BOOM 문서도 ALU에 단계를 추가해 다른 파이프라인 연산과 지연을 맞추고 공유 쓰기 포트의 스케줄링을 단순화하는 사례를 보여 준다. BOOM, The Execute Pipeline의 파이프라인 예
이 결론은 같은 포트에 매 사이클 최대 하나를 보내는 흐름과 고정된 지연이라는 전제가 있다. 여러 issue 포트에서 독립적으로 같은 쓰기 포트에 보낸다면 지연이 같아도 동시에 끝날 수 있다. 지연 통일은 특정 구조에서 충돌 예측을 쉽게 하는 수단이며 모든 공유 포트를 해결하는 규칙은 아니다.
지연과 새 입력을 받는 간격은 다르다
BOOM이 설명하는 pipelined functional unit은 고정 지연을 갖고 매 사이클 새 연산을 받을 수 있다. 지연이 3이어도 내부에 서로 다른 연산이 겹쳐 지나가므로 결과를 매 사이클 낼 수 있다. 반면 문서의 비파이프라인 나눗셈 장치는 연산 중 새 입력을 받지 않으며 완료 시간이 가변적이다. BOOM, Pipelined와 Un-pipelined Functional Units
따라서 “세 사이클짜리 장치니까 세 사이클마다 결과가 하나 나온다”는 계산은 파이프라인인지 확인하지 않으면 틀린다. 입력을 받아들이는 처리율과 결과가 머무는 시간은 writeback 유입량을 서로 다른 방식으로 결정한다.
완료 시점이 가변적이면 고정 지연 예약만으로는 충분하지 않다. 결과가 생긴 뒤 중재하거나, 완성된 결과를 담을 공간을 확보하거나, 충돌하지 않도록 실행을 제한하는 등의 계약이 필요하다. 실제 장치가 멈출 수 없는 출력 경로를 가진다면, 단순히 ready를 낮추라는 말로 그 결과를 보존할 수는 없다. 장치 인터페이스가 보장하는 저장과 정지 가능 범위를 먼저 확인해야 한다.
선택되지 않은 결과가 다음 사이클에도 있어야 한다
앞의 사이클 4에 P를 먼저 쓰기로 했다고 하자. Q의 결과를 한 사이클 보관할 수 있는 가상 출력 버퍼가 있다면, Q는 사이클 5에 쓸 수 있다. 그동안 결과 데이터와 목적지 번호는 함께 남아 있어야 한다. 유효 표시만 유지하고 데이터가 다음 연산으로 바뀌면 다른 값을 잘못된 번호에 쓸 수 있다.
버퍼에서 결과를 지우는 기준도 중요하다. 중재기에서 요청을 보았다는 사실이 실제 포트가 결과를 받았다는 사실과 같지 않을 수 있다. 전달이 수락된 시점에 소유권을 옮기고, 그렇지 않으면 보존한다는 규칙을 모든 단계가 공유해야 한다. 취소된 경로의 결과를 버리는 판단은 유효한 결과를 포트 충돌 때문에 잃는 것과 구분해야 한다. BOOM의 실행 장치 설명 역시 취소된 명령의 응답을 유효하지 않게 만드는 처리를 명시한다.
유한 버퍼가 지속적인 처리율 부족까지 해결하지는 않는다. 빈 버퍼에서 시작해 어떤 10사이클 구간에 결과 14개가 들어왔고 포트가 최대 10개를 처리했다면, 구간 끝에 적어도 4개가 남거나 입력을 제한해야 한다. 잠깐의 동시 도착과 평균 유입량이 포트 용량을 넘는 상황은 서로 다른 설계 문제다.
현재의 ready가 도착 시점의 약속은 아닐 수 있다
쓰기 포트뿐 아니라 장치에 명령을 전달하는 길에서도 시간의 차이를 조심해야 한다. BOOM의 부동소수점 divide/sqrt 설명에는 현재 ready가 다음 사이클에도 유지된다는 보장이 없는 인터페이스가 등장한다. issue 단계에서 보낸 명령이 뒤늦게 장치에 도착할 때 수락되지 않을 수 있는 것이다. 문서는 추가 버퍼에서 명령을 보관하고, 버퍼가 차면 issue 쪽에 backpressure를 전달하는 방법을 설명한다. BOOM, Floating Point Divide and Square-root Unit
이 사례는 가변 지연 장치를 붙일 때 현재 상태만 읽고 미래의 수락을 가정하면 안 된다는 점을 보여 준다. writeback에도 같은 질문을 해야 한다. 결과가 도착했는데 포트를 못 받으면 어디에 남는가, 공간이 차면 어디까지 유입을 막을 수 있는가.
writeback 중재가 제대로 작동하면 동시에 끝난 P와 Q는 모두 자신의 목적지에 한 번씩 반영된다. 고정 지연에서는 도착을 미리 정리하고, 예측하기 어려운 도착에는 보관과 수락 규칙을 둔다. 포트 하나의 처리 능력을 넘지 않도록 입력까지 연결해야, 계산을 끝낸 결과가 성능 경쟁 중에 사라지지 않는다.