DeepDataFlow
Earlgrey in G2 · 6편 중 4편

별도 도구에서 하는 사인오프

내보낼 파일로 완성된 칩의 타이밍을 분석하자, 계층 흐름에서만 나타나는 OpenROAD 버그 두 개가 드러났습니다. 둘 다 고쳐 업스트림에 보냈고, 그다음 우리 작업을 스스로 점검했습니다.

게시일 2026-10-22 · 6편 중 4편 · DeepDataFlow

3편이 끝났을 때 칩 v5는 배선과 피니시를 마쳤고, 배선 위반 15,056개는 알려진 남은 문제로 기록되어 있었습니다. 다음 단계는 사인오프 타이밍이었습니다. 업계에서 하는 방식대로 진행했고, 바로 그 선택이 버그를 찾아냈습니다.

사인오프는 내보내는 것을 읽습니다

배치 배선 도구는 자체 데이터베이스에서 타이밍을 보고할 수 있고, OpenROAD도 그렇게 할 수 있습니다. 하지만 파운드리나 계층의 다음 레벨로 가는 것은 파일입니다. 배치 배선 도구가 출력한 넷리스트와 기생 성분(SPEF)입니다. 사인오프는 별도 도구에서 그 파일들을 읽어야 합니다. 그래서 프로젝트 규칙은 사인오프는 별도 도구에서였습니다. OpenRCX가 기생 성분을 추출하고, OpenROAD가 넷리스트와 SPEF를 쓰고, 독립 실행 OpenSTA가 그것을 읽습니다.

배치 배선 도구 안의 타이밍은 자체 데이터베이스를 읽습니다. 사인오프는 출력된 파일을 읽습니다.
배치 배선 도구 안의 타이밍은 자체 데이터베이스를 읽습니다. 사인오프는 출력된 파일을 읽습니다.

추출에는 모든 메탈 층에 대한 규칙이 필요한데, sky130에는 층이 다섯 개뿐입니다. 저희의 10층 대체 스택에서 OpenRCX는 기본 규칙으로 오류를 보고하는 대신 비정상 종료되었습니다. 그래서 위층이 아래층을 복사하는 규칙(메탈 6~8은 메탈 4로, 메탈 9~10은 메탈 5로)을 만들고, 거기서 코너 네 개를 만들었습니다. cworst와 cbest는 ±10%입니다. 이 규칙은 가짜이며, 수치가 나오는 곳마다 그렇게 밝힙니다.

G2에서 추출은 독립된 단계입니다. 완성된 설계를 읽고, 코너마다 SPEF 하나를 쓰고, 그 파일들을 설계 데이터 관리자에 넷리스트와 나란히 체크인합니다. OpenSTA 시나리오는 둘 다 거기서 가져옵니다.

2:38

YouTube에서 보기(영어) ↗Bilibili에서 보기(중국어) ↗

버그 1: 기생 성분이 없는 드라이버 98,251개

첫 독립 실행 OpenSTA는 드라이버 98,251개에 기생 성분이 없다고 경고했고, "instance not found" 메시지 48,926개와 "net not found" 메시지 431,493개도 함께 나왔습니다. 그 드라이버 중 약 77,000개는 배선된 와이어가 전혀 없으므로 예상된 결과입니다. 나머지 21,000개는 실제 와이어였고, 대부분이 클록 트리 전체였습니다.

그런데 OpenROAD가 같은 SPEF로 자기 데이터베이스를 읽으면 490개를 제외한 모든 이름이 맞았습니다. 그 파일은 그것을 쓴 도구에는 괜찮았고, 다른 모든 도구에는 깨져 있었습니다.

틀린 첫 번째 이론

Claude Code의 첫 답은 클록 트리 도구가 버퍼 이름을 잘못 붙였다는 것이었습니다. 그럴듯한 이야기였고, 이를 뒷받침하려고 버퍼 하나를 추적해 두기도 했습니다. 엔지니어는 다른 질문을 했습니다. 같은 파일이 그 모듈의 합성된 넷은 계층 경로와 함께 올바르게 씁니다. 출력기가 거기서는 제대로 하고 여기서는 잘못하는 것은 무엇일까요?

그 질문은 CTS가 아니라 출력기를 가리켰습니다. 도구가 서브모듈 안에 만든 객체는 이름과 그것이 속한 모듈로 저장됩니다. 넷리스트 출력기는 모듈을 읽습니다. write_spef는 읽지 않았고, 그래서 CTS가 계층 안에 만든 모든 버퍼가 경로 없이 기록되었습니다.

원인을 찾은 질문: 같은 출력기가 제대로 하는 것과 비교하세요.
원인을 찾은 질문: 같은 출력기가 제대로 하는 것과 비교하세요.

OpenROAD의 write_spef를 고치고, 회귀 테스트를 추가하고, 기존 계층 테스트를 돌렸습니다. 60개 모두 변화가 없었습니다. 칩에서 "instance not found"는 48,926개에서 0개로, "net not found"는 431,493개에서 164개로 줄었습니다. 틀린 첫 번째 이론을 포함한 전체 조사 과정이 수정 전후 수치와 함께 문서로 남아 있습니다.

왜 이것이 전에는 드러나지 않았을까요? OpenROAD 안에서는 데이터베이스가 평탄하고 완전하므로 이름이 항상 해석됩니다. 출력된 파일을 읽어야만 버그가 드러납니다. 이것이 사인오프를 분리하는 가장 큰 이유입니다. 두 번째 규칙도 나왔습니다. 타이밍을 우회하지 말고 데이터를 고치세요.

버그 2: 잘못된 모듈에 들어간 더미 부하

클록 트리의 리프 넷에 빈틈이 하나 남아 있었습니다. 더미 부하는 클록 트리 도구가 가지의 균형을 맞추려고 추가하는 작은 셀입니다. 저희 칩에서 모든 클록 버퍼는 top_earlgrey 모듈 안에 있었는데, CTS는 더미 부하 14,348개를 칩의 최상위 모듈에 만들었고, 두 모듈 사이에는 포트가 없었습니다.

OpenROAD 안에서는 데이터베이스가 평탄하므로 각각은 여전히 하나의 넷입니다. 하지만 넷리스트 출력기는 같은 이름의 넷 두 개를 씁니다. 드라이버는 있고 와이어가 없는 넷과, 와이어는 있고 드라이버가 없는 넷입니다. 클록 넷 13,566개가 이렇게 나뉘었고, 클록 배선 커패시턴스 619 pF 중 206.7 pF(33%)가 잘못된 쪽에 들어갔습니다.

1:57

YouTube에서 보기(영어) ↗Bilibili에서 보기(중국어) ↗

잘못된 모듈에 들어간 더미 부하는 출력된 넷리스트에서 클록 넷 하나를 둘로 나눕니다.
잘못된 모듈에 들어간 더미 부하는 출력된 넷리스트에서 클록 넷 하나를 둘로 나눕니다.

CTS의 수정: 각 더미 부하를 그것이 부하로 걸리는 버퍼의 모듈에 만듭니다. 새 테스트는 다른 것도 보여 주었습니다. OpenROAD의 기존 참조 출력 중 하나(gated_clock4)에 이미 같은 분할이 들어 있었고, 최상위 모듈에 더미 부하가 18개 있었습니다. 골든 파일에도 버그가 있을 수 있습니다. 나머지 CTS 테스트 53개는 변화가 없었습니다.

칩을 CTS부터 다시 돌리면 하루 이상 걸렸을 것입니다. 대신 5분짜리 스크립트로 완성된 v5 데이터베이스의 더미 부하 13,553개를 올바른 모듈로 옮기고, 추출과 타이밍을 다시 돌렸습니다.

24,531 → 13,531 → 8기생 성분이 없는 클록 버퍼: 수정 전, SPEF 수정 후, CTS 수정 후
142,733 → 112OpenSTA의 "not connected" 경고
98,251 → 73,824기생 성분이 없는 드라이버, 대부분은 와이어가 전혀 없음

업스트림으로

두 버그 모두 OpenROAD로 계층 흐름을 돌리는 모든 사람에게 영향을 주므로 업스트림에 보냈습니다.

  • 각 버그를 OpenROAD 자체 테스트 방식으로 셀 몇 개만으로 재현했고, 먼저 최신 업스트림에서 확인했습니다.
  • 전체 테스트 스위트를 참조 출력과 비교했습니다. rcx, cts, dbSta는 142개 중 142개가 통과했고, rsz는 295개 중 294개로 변경 전과 같았습니다.
  • 수정마다 브랜치 하나.
  • 엔지니어가 승인하기 전에는 아무것도 게시하지 않았습니다.

결과는 이슈 두 개와 풀 리퀘스트 두 개입니다. 이슈 #11839와 #11840, 그리고 풀 리퀘스트 #11841과 #11842입니다. 2026-10-22 기준으로 모두 열려 있고 리뷰를 기다리고 있습니다.

그리고 우리 작업을 점검했습니다

G2 도구 묶음의 OpenROAD를 업그레이드한 뒤, 더 작은 샌드박스 칩들에서 두 가지 문제가 나타났습니다. 패드 링의 접지 끊김과, 기생 성분이 없는 클록 넷입니다. Earlgrey에도 있었을까요? 검사는 테스트 버전 v5a에 넣었습니다. 단계 두 개이고 새로운 배치 배선은 없으며, 다른 실행과 마찬가지로 버전 표에 기록됩니다.

1:51

YouTube에서 보기(영어) ↗Bilibili에서 보기(중국어) ↗

전원 그리드. 플로어플랜에 대한 검사에서 VDD 끊김이 발견되었습니다. 전원 그리드 도형 416개와 패드 전원 핀 1,000개 이상이 연결되어 있지 않았습니다. 저희의 전원 그리드 스크립트가 패드 층을 지정하지 않고 패드에 연결하기 때문입니다. 칩 v2부터 숨어 있던 저희 자신의 실수이며, 다음 버전을 위한 수정 방법은 알고 있습니다.

검사 자체에도 문제가 있었습니다. 끊김 검사는 약 1분이 걸렸는데, 그다음 OpenROAD의 단락 검사가 아무 출력 없이 코어 하나로 9시간 20분 동안 돌았습니다. 이를 중단하고, 이미 써 둔 결과를 보관하고, 버그로 등록했습니다. VSS는 검사하지 않았고, 이것도 목록에 있습니다.

기생 성분. 같은 넷리스트와 SPEF에 대해 프로브를 돌렸습니다. 기생 성분이 없는 드라이버 73,824개라고 하면 나빠 보이지만, 원인별로 정리하면 거의 전부가 와이어가 없거나(71,633개) 부하가 없거나(1,939개) 포트입니다. 실제로 무언가를 구동하는 것은 120개뿐입니다. 진짜 빈틈이고, 작습니다.

G2의 v5a 테스트 버전: README에 목적, 결과, 다음 단계가 있고, 결과는 버전 표에도 있습니다.
G2의 v5a 테스트 버전: README에 목적, 결과, 다음 단계가 있고, 결과는 버전 표에도 있습니다.

하나는 나쁜 소식이었고 하나는 좋은 소식이었으며, 둘 다 다음 사람이 볼 곳에 적혀 있습니다. 버전 표의 메모 한 줄, README, 버그 목록, 그리고 재개 페이지입니다.

사인오프 수치와 주의 사항

두 수정을 모두 적용한 뒤, 저속 코너(ss, cworst)의 톱 레벨 reg2reg 셋업 슬랙은 10 MHz에서 −7.87 ns이며, 클록이 없는 레지스터 클록 핀은 없습니다. 입출력 경로에는 아직 타이밍 예외가 없어서 그 수치는 아직 의미가 없고, 홀드 리포트도 없습니다. 이것들과 VDD 수정은 칩 v6 계획에 들어 있습니다.

다음: 엔지니어와 Claude Code가 일을 어떻게 나눴는지, 엔지니어가 잠든 밤까지 포함해서 이야기합니다.