---
title: "래치에서 빌린 시간이 다음 단계의 여유를 줄이는 과정"
author: "브레이브브라우저쓰자"
published_at: "2026-10-23T06:50:04.360Z"
updated_at: "2026-10-06T01:55:11.082Z"
tags: ["time borrowing"]
canonical_url: "https://ariser.io/@writer_a9817d5a8de0/%EB%9E%98%EC%B9%98%EC%97%90%EC%84%9C-%EB%B9%8C%EB%A6%B0-%EC%8B%9C%EA%B0%84%EC%9D%B4-%EB%8B%A4%EC%9D%8C-%EB%8B%A8%EA%B3%84%EC%9D%98-%EC%97%AC%EC%9C%A0%EB%A5%BC-%EC%A4%84%EC%9D%B4%EB%8A%94-%EA%B3%BC%EC%A0%95"
ai_assisted: true
---

# 래치에서 빌린 시간이 다음 단계의 여유를 줄이는 과정

이 글은 AI가 활용됐습니다.

[원문](https://ariser.io/@writer_a9817d5a8de0/%EB%9E%98%EC%B9%98%EC%97%90%EC%84%9C-%EB%B9%8C%EB%A6%B0-%EC%8B%9C%EA%B0%84%EC%9D%B4-%EB%8B%A4%EC%9D%8C-%EB%8B%A8%EA%B3%84%EC%9D%98-%EC%97%AC%EC%9C%A0%EB%A5%BC-%EC%A4%84%EC%9D%B4%EB%8A%94-%EA%B3%BC%EC%A0%95)

파이프라인의 한 단계가 예정된 경계를 조금 넘었다고 해서 항상 실패하는 것은 아니다. 저장 소자가 래치라면 입력을 통과시키는 구간이 있기 때문이다. 데이터가 래치가 열리는 순간보다 늦게 도착해도, 아직 닫히지 않았다면 전달될 수 있다. Time borrowing은 이 투명 구간을 이용하는 타이밍 동작이다. 다만 앞 단계가 얻은 시간은 다음 단계가 기다린 시간이기도 하다.

## 열리는 시각과 닫히는 시각은 역할이 다르다

플립플롭은 특정 클록 에지 주변에서 데이터를 샘플링한다. 래치는 enable이 활성인 동안 투명하고, 비활성으로 바뀌면 값을 보존한다. 따라서 래치를 통과하는 경로를 에지 하나로만 설명하면 중요한 정보가 빠진다. 입력 도착, 래치가 열리는 시각, 닫히기 전 setup 요구를 함께 읽어야 한다.

OpenSTA는 time borrowing을 투명 래치의 입력 데이터가 래치가 열린 뒤 도착하는 시간으로 정의한다. 예를 들어 열리는 시각이 5ns, 입력 도착이 6ns라면 빌린 시간은 1ns다. 주기가 10ns라고 해서 6ns 전체가 borrowing인 것도, 입력이 닫히기 전에 왔다고 해서 borrowing이 0인 것도 아니다. [set_max_time_borrow의 정의](https://opensta.readthedocs.io/en/latest/Commands/#set_max_time_borrow)

데이터가 열리기 전에 도착한 경우도 구분해야 한다. 래치가 닫혀 있을 때 들어온 새 값은 그 즉시 다음 단계로 전달되지 않는다. 열릴 때까지 기다린다. 이상화한 전달식을 `출력 변화 시각 = max(입력 도착, 열리는 시각) + 전달 지연`으로 쓰면 두 상황을 한눈에 비교할 수 있다. 이 식은 글의 계산용 모델이며 실제 라이브러리의 enable-to-Q와 data-to-Q 지연은 서로 다를 수 있다.

## 투명 구간이 남아도 다음 단계가 실패할 수 있다

가상 회로에서 래치는 5ns에 열려 10ns에 닫힌다고 하자. 앞 플립플롭은 0ns에 launch하고, 계산된 래치 입력 도착은 6ns다. 래치 전달 지연은 두 상황 모두 0.2ns로 가정한다. 래치 뒤 조합 논리의 최대 지연은 2.5ns, 다음 플립플롭은 10ns에 capture하며 setup 시간은 0.3ns다. 클록 도착 오차와 추가 여유는 생략한다.

입력은 1ns를 빌리고, 래치 출력은 6.2ns에 바뀐다. 다음 입력은 6.2 + 2.5 = 8.7ns에 도착한다. 목적지 요구 시간은 10 − 0.3 = 9.7ns이므로 slack은 +1.0ns다. 래치 입력이 3ns에 왔다면 출력을 3.2ns로 계산해서는 안 된다. 열리는 5ns를 기다려 출력은 5.2ns, 다음 입력은 7.7ns가 된다.

이제 앞 단계가 느려져 래치 입력이 9ns에 도착했다고 하자. 래치 자체의 닫힘 에지 setup 시간을 0.2ns로 놓으면 입력 마감은 9.8ns다. 9ns는 그 마감을 통과한다. 그러나 래치 출력은 9.2ns, 다음 플립플롭 입력은 11.7ns에 도착해 slack이 −2.0ns가 된다.

```text
다음 단계가 요구하는 래치 입력 마감
= 9.7 − 2.5 − 0.2 = 7.0 ns
이 경로에서 감당 가능한 borrowing
= 7.0 − 5.0 = 2.0 ns
```

래치 자체는 최대 4.8ns의 투명 구간을 활용할 수 있어도, 이 다음 단계는 2ns까지만 허용한다. Time borrowing을 잘 쓰려면 닫힘 조건과 후속 경로의 마감 중 더 엄격한 조건을 따라야 한다. 투명 구간의 길이가 곧 시스템 전체의 추가 예산은 아니다.

## 제약은 시간을 만들어 내지 않는다

`set_max_time_borrow`로 한도를 지정할 수 있다는 것은 설계자가 빌림을 제한할 수 있다는 뜻이다. 명령을 넣었다고 래치의 물리적인 투명 구간이 늘어나지는 않는다. OpenSTA의 실제 구현은 열린 클록과 닫힌 클록의 도착, setup margin, 지정된 한도 등을 이용해 허용 borrowing을 계산한다. 입력이 열리기 전에 도착한 경우와 투명할 때 도착한 경우도 분리한다. [Latches.cc의 latchRequired와 latchBorrowInfo](https://github.com/The-OpenROAD-Project/OpenSTA/blob/master/search/Latches.cc)

반대쪽 위험도 놓치기 쉽다. 최대 지연만 줄였다고 모든 조건을 만족한 것은 아니다. 매우 빠른 데이터는 래치들이 동시에 투명한 구간을 지나 예상보다 멀리 전달될 수 있다. 따라서 최소 지연, hold, 클록 위상의 겹침도 검토해야 한다. 특히 래치가 연결된 순환 경로는 각 구간에 시간을 따로 더하는 방식으로 결론을 내리기 어렵다. 같은 값이 어느 투명 구간에서 출발해 어느 닫힘 경계에 보존되는지 일관된 사이클 분석이 필요하다.

실무적으로 borrowing이 큰 경로를 봤다면 “늦었지만 통과했다”에서 멈추지 말고, 그 래치 뒤의 가장 엄격한 목적지를 따라가 보면 된다. 열리는 시각의 변경이나 duty cycle 오차는 앞 단계의 한도와 다음 단계의 시작을 함께 바꾸므로, 두 보고서를 같은 클록 모델로 읽어야 한다. 라이브러리의 래치 타이밍 모델 없이 래치를 일반 버퍼처럼 취급하는 것도 위험하다.

Time borrowing의 장점은 단계별 지연이 고르지 않을 때 시간 경계를 유연하게 사용할 수 있다는 데 있다. 그 유연함을 안전하게 쓰는 기준은 단순하다. 늦게 도착한 입력을 받아들일 수 있는지 확인하고, 그만큼 늦어진 출력이 다음 마감까지 도달하는지도 확인한다. 빌린 시간에는 반드시 빌려준 단계가 있다.

