모든 이야기

CDC reset 협상: 한쪽을 재시작했는데 거래가 하나 더 생긴다

두 클록 영역 사이의 전달은 잘 되는데, 한쪽 블록을 재시작한 뒤 갑자기 거래가 한 번 더 발생한다. 원천은 새 요청을 보내지 않았다. 데이터도 모두 0과 1로 안정되어 있다. 이런 오류는 준안정성 없이도 생긴다. CDC reset 협상은 신호를 초기값으로 돌리는 것과 함께, 상대가 기억하는 거래의 역사도 같은 경계에서 끝내는 절차다.

CDC는 clock domain crossing, 즉 서로 다른 클록 영역을 연결하는 구조다. 여기서는 이벤트마다 요청 비트를 뒤집고, 목적지가 수락하면 확인 비트를 맞추는 한 거래짜리 handshake를 생각하자. 요청과 확인이 같으면 비어 있고, 다르면 새 거래가 있다는 약속이다.

한쪽의 0은 상대에게 새로운 사건이다

정상 거래가 끝나 원천 request=1, 목적지 acknowledge=1이라고 하자. 두 비트가 같으므로 원천은 다음 요청을 보낼 수 있다. 그때 원천만 reset되어 request가 0으로 돌아가면 무엇이 일어날까.

목적지에서는 동기화 지연 뒤 request=0을 본다. 자신의 acknowledge는 여전히 1이다. 평소 규칙으로 해석하면 서로 다른 비트는 새 요청이다. reset이라는 사건이 요청 비트의 전이와 같은 형태로 나타났으므로, 목적지가 초기화된 payload를 정상 거래로 받아들일 수 있다.

시점원천 요청목적지 확인목적지 해석
거래 완료11대기 중
원천만 reset01아직 이전 관측 유지
reset 값이 전달됨01새 요청처럼 보일 수 있음

표는 논리적인 설명용 예다. 실제 구현의 요청 수신 레지스터와 데이터 저장 시점에 따라 세부 파형은 달라진다. 다만 초기값으로 돌아가는 전이가 프로토콜의 사건으로 해석될 수 있다는 문제는 남는다.

PULP의 기본 2-phase CDC는 운용 중 warm reset을 그대로 지원하는 모듈로 사용하지 말라는 조건을 명시한다. 전원 초기화 때 양쪽 reset의 assertion과 각 클록에 맞춘 deassertion도 구분한다. 정상 전달의 handshake가 있다는 사실만으로 한쪽 재시작까지 안전하다고 결론 낼 수 없다.

상태를 지우기 전에 거래를 보이지 않게 만들기

핵심은 상대가 이전 요청 상태와 초기화 중인 상태를 정상 데이터로 사용하지 않도록 순서를 만드는 것이다. 가능한 절차는 거래의 격리, 격리 완료의 확인, 양쪽 통신 상태의 초기화, 초기화 완료 확인, 격리 해제다.

격리는 원천에서 새 거래 수락을 막고, 목적지에서 유효한 거래를 외부에 제시하지 않는 상태를 뜻한다. 단순히 요청 비트를 reset하는 동작과 다르다. 현재 목적지가 데이터를 소비 중이라면 그 소비를 끝낼지 취소할지도 정의되어야 한다. 격리 완료의 확인은 그 결정이 실제 인터페이스에 반영되었음을 나타내야 한다.

PULP의 CDC reset controller는 양쪽의 isolate와 clear 순서를 협상하는 공개 구현이다. 원문의 설명은 isolate 요청 뒤 외부 회로의 isolate acknowledgment를 기다리고, clear를 진행한 뒤 다시 개방하는 관계를 보여 준다. reset 신호 하나를 상대에게 전달하는 것보다 강한 계약이다.

이 구현을 사용한다면 연결된 CDC의 동기 clear 지원, 격리 확인의 의미, 내부 협상과 데이터 경로의 동기화 지연 조건을 함께 만족시켜야 한다. controller를 옆에 배치했다는 사실만으로 기존 모듈에 없는 격리 기능이 생기지는 않는다.

진행 중 거래는 사라져도 되는가

가상의 통신 블록에 거래 A가 하나 남아 있을 때 reset이 요청되었다고 하자. 정책이 drain이면 A의 전달 완료를 기다린 뒤 격리와 clear를 수행한다. 정책이 abort이면 A를 취소하고, 원천 또는 상위 계층에 취소 사실을 알려야 한다. 두 정책은 관측 결과가 다르므로 같은 reset 파형으로 설명할 수 없다.

목적지가 이미 외부 장치에 A를 실행했지만 완료 확인이 원천으로 돌아오기 전에 reset되었다면 더 어려워진다. 원천은 A가 실행되지 않았다고 생각해 다시 보낼 수 있다. 통신 내부를 양쪽 모두 초기화해도 이미 발생한 외부 부작용은 되돌아가지 않는다.

따라서 “reset 이후 비어 있다”는 상태와 “이전 거래가 실행되지 않았다”는 보장은 다르다. exactly-once가 필요하다면 거래 식별자, 완료 기록, 상위 계층의 복구 정책 같은 추가 책임이 필요할 수 있다. reset 협상의 범위를 링크 내부의 상태 정합성과 외부 거래의 의미로 나누어 적어야 한다.

재시작 시간도 상대의 상태에 의존한다

양쪽 클록이 움직이고 상대가 격리를 받아들여야 협상이 진행된다. 어느 클록이 정지해 있다면 일반적인 동기 handshake는 응답을 기다릴 수 있다. 전원 관리가 “reset 완료 후 클록 공급”을 요구하고 협상이 “클록이 있어야 reset 완료”를 요구하면 교착한다.

그러므로 timeout을 임의로 넣어 격리를 해제하기 전에, 기다리는 상태가 안전하게 유지되는지와 시간 제한 뒤 어떤 복구로 넘어가는지를 정해야 한다. 정확한 완료 시간은 사용하는 모듈의 단계 수와 클록, 외부 격리 응답에 달려 있다. 이 글의 순서를 특정 구현의 보장된 사이클 수로 읽으면 안 된다.

검증에서는 대기 중뿐 아니라 요청 전달 중, 데이터 수락 직후, 확인 복귀 중에 각각 한쪽 reset을 넣어 보자. 양쪽 동시 reset과 서로 다른 해제 순서도 필요하다. 취소된 거래가 나중에 되살아나거나 완료 거래가 반복되지 않는지를 거래 단위로 비교해야 한다.

처음의 가짜 거래는 초기값이 틀려서 생긴 것이 아니었다. 한쪽만 초기값으로 돌아가고 상대의 역사 해석은 남아 있었기 때문이다. CDC reset 협상의 답은 양쪽에 0을 쓰는 것이 아니라, 이전 거래를 어디서 끝내고 언제부터 새 거래를 허용할지 함께 결정하는 것이다. 그 경계를 정의해야 재시작이 새로운 요청처럼 보이지 않는다.

CDC reset 협상: 한쪽을 재시작했는데 거래가 하나 더 생긴다 · ariser