모든 이야기

레지스터를 옮기면 리셋값의 의미도 함께 옮겨야 한다

긴 조합 경로를 짧게 만들려고 레지스터를 옮겼다. 입력에서 출력까지의 레지스터 수는 같으니 기능도 같을까? retiming은 이 직관을 정밀한 변환으로 다룬다. 레지스터 경계를 바꾸면서도 외부에서 보는 입력·출력의 시간 관계를 보존해야 하며, 시작 상태와 제어 동작도 그 관계에 맞아야 한다.

느린 구간을 나눠도 전체 지연을 늘릴 필요는 없다

Leiserson과 Saxe의 원 논문은 조합 기능을 그래프의 정점으로, 연결의 레지스터 수를 에지의 가중치로 표현한다. 레지스터를 어떤 연결에서 빼고 다른 연결에 더해 조합 경로를 바꾸는 변환을 정의한다. 같은 기능을 보존하며 긴 경로의 지연을 줄이는 것이 목적이고, 단순히 파이프라인 단계를 추가해 전체 지연을 늘리는 선택과 구분한다. Retiming Synchronous Circuitry 원 논문

가상 단일 경로에 100ps, 300ps, 200ps의 조합 블록이 순서대로 있다고 하자. 입력 쪽과 출력 쪽의 고정 레지스터 사이에 내부 레지스터가 하나 더 있다. 내부 경계를 첫 블록 뒤에 두면 두 구간의 조합 지연은 100ps와 500ps다. 경계를 두 번째 블록 뒤로 옮기면 400ps와 200ps가 된다.

이상적인 고정 지연 모델에서 가장 긴 구간은 500ps에서 400ps로 줄어든다. 경로의 레지스터 수는 추가하지 않았다. 그러나 이 숫자만으로 변환의 기능을 증명한 것은 아니다. 옮긴 경계의 상태가 무엇을 표현하는지와 초기값, 다른 분기 입력이 같은 시점의 데이터인지까지 확인해야 한다. 실제 클록 제약에는 clk-to-Q, setup, 배선과 클록의 차이도 더해진다.

원문의 리타이밍 관계는 정점의 이동량 r을 사용해 에지의 레지스터 수를 w'(u,v) = w(u,v) + r(v) − r(u)로 정한다. 계산된 수가 음수가 되면 실제 레지스터로 구현할 수 없어 적법한 변환이 아니다. 여러 입력이 있는 연산에서 한 경로만 무작정 옮기는 대신 연결 전체의 관계를 다루는 이유다.

인버터 하나에서도 리셋값은 바뀐다

기능 보존의 조건을 가장 작은 회로로 보자. 1비트 x를 레지스터 r에 저장하고, 출력 y는 r의 반전값이라고 하자. 리셋하면 r=0이며, enable이 1인 에지에서만 입력을 캡처한다.

always @(posedge clk)
  if (rst)     r <= 1'b0;
  else if (en) r <= x;
assign y_before = ~r;

이제 인버터를 레지스터 앞쪽으로 옮기고 새 레지스터 s를 바로 출력한다고 하자. 정상 입력을 저장하는 식은 s<=~x가 된다. 그러나 s의 리셋값까지 0으로 복사하면 리셋 뒤 y_before=1, y_after=0으로 즉시 달라진다.

두 회로의 상태 관계는 r=s가 아니라 s = ~r이어야 한다. 그러므로 s를 1로 리셋해야 한다.

always @(posedge clk)
  if (rst)     s <= 1'b1;
  else if (en) s <= ~x;
assign y_after = s;

공통 리셋에서 r=0, s=1이면 출력은 둘 다 1이다. en=1인 다음 에지에 x=1을 넣으면 r=1, s=0이 돼 출력은 둘 다 0이다. en=0인 동안은 두 상태를 유지하므로 반전 관계도 유지된다. 다시 en=1에서 x=0을 넣으면 r=0, s=1, 두 출력은 1이다. 이 예는 상태 관계를 직접 계산한 것이며 실제 리타이밍 도구의 결과가 아니다.

제어와 관측 시점까지 함께 보존하기

위 예에서 enable을 새 회로에 적용하지 않으면 대기 중 x가 바뀔 때 s도 새 값을 저장한다. 원래 r은 유지되므로 두 출력이 달라진다. 같은 레지스터 수나 같은 정상 캡처 식만으로는 enable 조건을 보존한 것이 아니다. 리셋의 동기·비동기 방식과 극성, 레지스터가 갖는 다른 제어도 같은 주의를 요구한다.

큰 연산의 앞뒤로 레지스터를 옮길 때는 필요한 초기 상태를 새 구조에서 만들 수 있는지도 확인해야 한다. 조합 함수가 되돌릴 수 없는 함수라면 원하는 초기 출력 상태에 맞는 입력 레지스터 값을 찾기 어려운 경우가 있다. 여러 분기에서 들어오는 데이터의 주기 대응도 함께 유지해야 한다. 단순히 한 경로가 빨라졌다는 사실로 이 제약들을 해결할 수는 없다.

검증에서는 내부 레지스터 비트가 직접 같은지 비교하기보다, 올바른 상태 관계에서 외부 출력이 같은 시점에 같은 값을 갖는지 확인한다. 초기값이 없거나 X가 있는 경우의 비교 의미도 명시해야 한다. EQY의 문서는 초기 조건과 X의 해석이 등가성 관계를 바꿀 수 있음을 설명한다. EQY의 초기 상태와 등가성 조건

외부에서 한 클록 늦은 출력을 허용하는 새 계약을 만드는 일도 가능하지만, 그것은 같은 출력 타이밍을 보존했다는 주장과 다른 검증 조건이다. 리타이밍의 효과를 보고할 때는 유지한 입출력 지연과 바뀐 내부 상태의 대응을 함께 보여 주면 된다.

레지스터를 옮긴 회로를 평가할 때는 줄어든 가장 긴 조합 구간부터 보되, 그다음에는 초기·리셋·enable과 출력의 주기 관계를 검사한다. 인버터 뒤의 0이 인버터 앞에서는 1에 대응한다는 작은 예를 끝까지 확인하면, 경계 이동은 레지스터의 위치뿐 아니라 상태의 의미를 옮기는 작업임을 알 수 있다.