---
title: "functional coverage: 두 개의 100% 뒤에 비어 있는 조합"
author: "브레이브브라우저쓰자"
published_at: "2026-10-18T09:56:00.963Z"
updated_at: "2026-10-06T00:59:05.608Z"
tags: ["functional coverage"]
canonical_url: "https://ariser.io/@writer_a9817d5a8de0/functional-coverage-%EB%91%90-%EA%B0%9C%EC%9D%98-100-%EB%92%A4%EC%97%90-%EB%B9%84%EC%96%B4-%EC%9E%88%EB%8A%94-%EC%A1%B0%ED%95%A9"
ai_assisted: true
---

# functional coverage: 두 개의 100% 뒤에 비어 있는 조합

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

[원문](https://ariser.io/@writer_a9817d5a8de0/functional-coverage-%EB%91%90-%EA%B0%9C%EC%9D%98-100-%EB%92%A4%EC%97%90-%EB%B9%84%EC%96%B4-%EC%9E%88%EB%8A%94-%EC%A1%B0%ED%95%A9)

깊이 4인 FIFO의 테스트 보고서에서 모든 점유율을 보았고 모든 요청 종류를 보았다고 나온다. 두 지표는 각각 100%다. 그런데 가득 찬 FIFO에서 push와 pop을 동시에 요청한 적은 없을 수 있다. 개별 항목을 한 번씩 본 사실과 그 항목들이 함께 발생한 사실은 같지 않다.

functional coverage는 명세에서 중요하다고 정한 상황이 실제로 관찰되었는지 기록한다. 어떤 상황을 세도록 정의했는지가 백분율보다 먼저다.

## 분모는 회로가 아니라 검증 계획에서 온다

UVM User’s Guide는 명시적으로 정한 기능 목표를 세는 coverage와 코드의 실행을 측정하는 지표를 구분한다. 기능 목표는 높은 수준의 동시 발생을 표현할 수 있지만, 적어 놓지 않은 요구는 그 보고서에 나타나지 않는다. 코드 지표 역시 명세 요구를 모두 대신하지 못한다. [Accellera UVM User’s Guide 1.1, §4.11 Implementing Functional Coverage](https://www.accellera.org/images/downloads/standards/uvm/uvm_users_guide_1.1.pdf)

FIFO 예에서 edge 직전의 점유율은 0~4다. 요청은 idle, push만, pop만, push와 pop 동시의 네 종류다. 이 가상 인터페이스는 빈 상태의 pop 요청이나 가득 찬 상태의 push 요청도 허용하되, 수락 여부와 응답을 명세대로 처리한다고 정한다. 요청 자체를 금지하는 인터페이스라면 이후의 분모가 달라진다.

점유율에 다섯 bin, 요청 종류에 네 bin을 만들자. 다음의 관측 기록은 서로 다른 시점에서 모았으며 중간의 상태 이동 과정은 표에서 생략했다.

| 관측한 점유율 | 그때의 요청 |
|---:|---|
| 0 | idle |
| 1 | push만 |
| 2 | pop만 |
| 3 | 동시 요청 |
| 4 | idle |

점유율의 다섯 bin과 요청의 네 bin을 모두 보았으므로 각각의 지표는 100%다. 그러나 `점유율 × 요청 종류`의 cross를 만들면 가능한 조합은 5×4=20개이고, 표에서 본 조합은 5개다. cross coverage는 25%다.

가득 찬 상태의 동시 요청은 이 다섯 개에 없다. 두 개의 100%를 평균 내거나 곁에 표시해도 그 빠진 조합이 채워지지 않는다. 요구사항이 ‘full 상태에서 동시에 요청할 때도 정해진 수락 정책을 지킨다’라면, 그 조합을 별도 목표로 정의해야 한다.

## 많이 실행한 코드가 특정 동작을 보장하지 않는다

코드 coverage는 다른 질문에 답한다. 어떤 줄이나 분기가 실행되었는지, 어떤 신호가 바뀌었는지는 구현의 실행 흔적이다. 예를 들어 full 처리 분기는 push만 요청했을 때 실행되고, 동시 요청 처리 분기는 점유율 3일 때 실행될 수 있다. 두 분기를 각각 지나도 full과 동시 요청이 만나는 경계는 보지 않았을 수 있다.

Verilator의 공식 문서도 line coverage를 코드 제어 흐름 지점의 실행으로, toggle coverage를 신호 bit의 변화로 설명한다. 별도의 기능 coverage와 property coverage도 제공한다. 도구가 어떤 항목을 지원하는지와 그 항목이 어떤 요구를 표현하는지는 구분해야 한다. [Verilator, Coverage Analysis](https://verilator.org/guide/latest/simulating.html)

또한 coverage는 보통 ‘발생했다’를 센다. 해당 입력에서 출력이 옳았는지까지 자동으로 증명하지 않는다. full·동시 요청 bin을 채운 순간 FIFO가 잘못된 데이터를 내보내도, 그 오류를 잡을 별도 checker가 없으면 상황은 관측된 것으로 남을 수 있다. coverage를 수집하는 것과 정답을 검사하는 일을 함께 설계해야 한다.

## 불가능한 조합은 근거를 가지고 제외한다

cross를 늘리면 빈 bin이 많이 생긴다. 일부는 자극이 부족해서 비었고, 일부는 명세상 발생할 수 없어서 비었다. 이를 같은 방식으로 처리하면 보고서가 판단을 흐린다.

예를 들어 별도의 프로토콜이 full 상태의 push 요청을 아예 불법으로 정했다면 그 요청 조합은 일반적인 성공 목표에서 제외할 수 있다. 그러나 현재 예의 인터페이스처럼 요청은 허용하고 수락을 제한하는 계약이라면 full·push가 비었다고 ‘불가능’으로 제외할 근거가 없다. RTL에서 지금 관측되지 않는다는 사실만으로 명세상 불가능하다고 판단해서도 안 된다.

불법 상황을 표현할 때도 coverage만 믿지는 않는다. lowRISC 가이드는 `illegal_bins`를 유일한 checker로 사용하지 말고, coverage 수집 여부와 독립적으로 관련 검사를 두도록 권한다. 불법 bin의 처리를 모든 시뮬레이터에서 동일한 테스트 실패로 가정하지 않기 위해서다. [lowRISC DV Coding Style, Functional Coverage](https://github.com/lowRISC/style-guides/blob/master/DVCodingStyle.md)

샘플링 기준도 목표와 맞아야 한다. 수락된 전송의 종류를 세는 목표라면 실제 handshake를 기준으로 하고, 거절된 요청에 대한 반응을 확인하려면 그 요청 자체를 관측한다. 점유율은 해당 edge에서 처리하기 전인지 후인지 명시한다. 정의가 섞이면 같은 bin 이름에 서로 다른 사건이 쌓인다.

functional coverage의 100%는 정의한 bin을 채웠다는 의미다. 정의에서 빠진 요구나 잘못된 결과까지 해결했다는 뜻은 아니다. 점유율과 요청을 각각 본 데서 멈추지 않고 중요한 조합을 목표로 만들고, 그 순간의 결과를 검사해야 한다. 보고서의 숫자를 검증 완료로 읽기 전에 그 숫자의 분모와 관측 기준을 읽어야 한다.

