구글 안티그래비티 완전 분석 — 모델·요금제·CLI 총정리

🚀 구글 안티그래비티(Antigravity) 완전 분석 구글이 2025년 11월 Gemini 3와 함께 공개한 에이전트 퍼스트(agent-first) IDE 안티그래비티는 Claude·GPT·Gemini를 한 도구에서 골라 쓰는 멀티모델 코딩 환경이다. 이 글에서는 ① 지원 모델과 요금제별 사용량의 실체, ② 실사용자 평가, ③ 구글의 방향성, ④ Claude Code와의 비교·연계, ⑤ CLI( agy )로 직접 쓰는 법까지 다섯 갈래를 차례로 정리한다. 자료 간 충돌이 있는 지점은 한쪽으로 단정하지 않고 양쪽을 모두 살려 표기했다. 📅 기준 시점: 2026년 6월 · 프리뷰 단계 정보로 수치는 변동 가능 1. 안티그래비티란 무엇인가 — 기초 정리 안티그래비티는 2025년 7월 구글이 24억 달러 규모 라이선스 계약 으로 영입한 전 Windsurf 팀이 설계를 주도했다. VSCode를 포크한 위에 자율 에이전트 오케스트레이션 계층을 얹은 구조다. 2026년 5월 Google I/O에서 발표된 안티그래비티 2.0 은 데스크탑 앱과 함께 공식 CLI agy 를 처음 공개하며 기존 Gemini CLI의 공식 후계자 자리를 확정했다. 핵심 정체성은 단순 코드 자동완성이 아니라 병렬 에이전트 오케스트레이션 이다. 여러 에이전트가 동시에 — 하나는 API, 하나는 테스트, 또 하나는 프론트엔드 — 작업을 나눠 진행하고, 각 에이전트는 계획·테스트 결과·스크린샷·영상을 담은 Artifact 를 남긴다. "사람이 한 줄씩 승인"하는 방식이 아니라 "에이전트들이 일을 마치고 사람이 사후 검수"하는 모델이다. flowchart TD A([사용자 작업 지시]) --> B[에이전트 A API 구현] A --> C[에이전트 B 테스트 작성] A --> D[에이전트 C UI 생성] B --> E[Artifact 계획·결과·영상] C --> E D --> E...

SystemVerilog automatic 키워드 완벽 가이드

SystemVerilog automatic 키워드 완벽 가이드

생명주기, 합성 가능성, 그리고 실무 설계 가이드까지 — IEEE 표준과 Synopsys·Xilinx·Intel 문서를 기준으로 정리합니다.

한 줄 요약: automatic은 스코프 진입마다 변수를 재할당하는 키워드로, Verilog의 정적 변수 모델과 달리 재진입 가능한 서브루틴과 안전한 동시 호출을 가능케 합니다. RTL용 모든 task/function에 명시하는 것이 시뮬레이션·합성 불일치를 막는 정답입니다.

1. 왜 automatic이 필요한가

SystemVerilog는 검증(UVM 클래스 메서드)과 합성(재진입 가능한 함수) 양쪽 요구를 동시에 만족해야 합니다. 그래서 두 가지 변수 생명주기(Variable Lifetime)를 정의합니다.

  • Static — 시뮬레이션 시작 시 1회 할당, 종료까지 유지 (Verilog 전통 방식)
  • Automatic — 스코프 진입마다 재할당, 종료 시 소멸 (소프트웨어 스택 프레임과 동일)

기본 생명주기 규칙 (혼동의 출발점)

선언 위치 기본 생명주기
module / interface / program / package 내부 static
class 메서드 내부 변수 automatic
for (int i ...) 루프 변수 automatic
task / function 내부 변수 상위 lifetime을 상속 (기본 static)

⚠️ 함정: 모듈 내부에 정의된 task/function은 자동으로 static이 됩니다. RTL 설계자가 무심코 task add(...)를 정의하면, 두 곳에서 동시 호출 시 내부 변수가 공유되어 데이터가 오염됩니다.

2. Static vs Automatic — 동작 차이 한눈에

관점 Static Automatic
초기화 시점 타임 0에서 1회 스코프 진입 시마다
메모리 공유 모든 호출이 동일 메모리 공유 호출마다 독립 인스턴스
재진입 안전성 ❌ race condition 위험 ✅ 안전
합성 매핑 공유 레지스터/와이어 호출 사이트별 복제(unroll)
대표 용도 상태 보존 카운터, 누적 변수 순수 계산, UVM 클래스 메서드

메모리 모델 흐름도

두 프로세스가 동시에 task 호출 Process A do_calc(3) Process B do_calc(7) Static (기본) temp = ? 공유 메모리 → 값 덮어쓰기 Automatic A: temp_A, B: temp_B 호출별 독립 → 안전 동일 task를 fork-join으로 동시 호출할 때 결과가 달라진다

3. 합성 가능성 — 스택 없는 하드웨어가 어떻게?

하드웨어에는 물리적 스택이 없습니다. 그렇다면 합성기는 automatic을 어떻게 처리할까요? 답은 두 가지입니다.

  • 임시 신호화 — automatic 변수를 조합 회로의 임시 wire 노드로 매핑
  • 호출 사이트 복제(Unrolling) — 함수가 N곳에서 호출되면 게이트 군을 N개 복제

주요 EDA 벤더 지원 현황

벤더 / 툴 지원 상태
Synopsys Design Compiler Task/Function의 automatic 완전 지원. 재귀는 깊이 제한 또는 unroll 가능 시에만.
Xilinx (AMD) Vivado 공식 지원. UG901(p.245)은 "동일 모듈 내 두 위치에서 동시 호출되는 task/function에는 automatic이 필수"라고 명시.
Intel Quartus Prime Pro/Std "Quartus Prime supports automatic variables in tasks and functions" — 공식 가이드 명시.

⚠️ 시뮬레이션-합성 비대칭: 시뮬레이터는 task/function 기본을 static으로 보지만, Vivado는 사실상 automatic처럼 처리합니다. 이 차이가 "시뮬은 OK인데 실리콘에서 망가지는" 전형적 버그의 진원지입니다.

재귀(Recursion)는 합성 가능한가?

재귀 함수 합성 재귀 깊이 = 컴파일 타임 상수? YES NO 정적 전개 곱셈기/덧셈기 체인으로 unroll 합성 거부 ELAB-311 too complex to unroll 예: parameter N의 factorial(N) → N단 곱셈기 체인 합성 OK

아래는 합성 가능한 재귀의 정석입니다. parameter N은 컴파일 타임 상수이므로 곱셈기 체인으로 풀립니다. N이 입력 포트라면 동적 깊이가 되어 합성은 실패합니다.

module factorial_module #(parameter N = 4) (
  output logic [31:0] out
);
  function automatic int factorial(int n);
    if (n <= 1) return 1;
    else    return n * factorial(n - 1);
  endfunction

  assign out = factorial(N);  // N이 상수이므로 unroll 가능
endmodule

4. 알려진 함정(Pitfalls) 3가지

함정 ① 선언 시점 초기화

int a = 5; 형태로 automatic 변수를 선언과 동시에 초기화하면, 시뮬레이터는 호출마다 5로 재설정하지만 일부 합성기는 이 초기값을 상수로 오인하거나 무시합니다.

→ Cliff Cummings(SNUG 2020) 권고: 선언과 할당을 분리하라.

함정 ② always_ff 내부에서의 오용

automatic 변수는 본질적으로 조합 임시 저장소입니다. always_ff 내부에서 값을 다음 클럭까지 유지하려 하면 의도치 않은 래치/플립플롭이 합성되거나 에러가 발생합니다. 상태 보존이 필요하면 반드시 logic 레지스터 + always_ff 조합으로 명시하세요.

함정 ③ 시뮬레이션-합성 기본값 차이

시뮬레이터 기본값은 static, Vivado 실제 동작은 사실상 automatic. 이 비대칭이 "Verilog 시뮬은 통과하지만 합성 후 다르게 동작"하는 가장 흔한 시나리오입니다.

→ 해결책: 모든 task/function에 automatic을 명시하여 양쪽을 한쪽으로 강제 정렬.

위험도 요약

동시 호출 race condition (automatic 누락 시) ★★★★★
시뮬-합성 기본값 불일치 ★★★★☆
선언 시 초기화 무시 ★★★☆☆

5. 실무 Best Practices 6가지

  1. 1합성용 task/function에는 항상 automatic을 명시. 시뮬레이션과 합성기의 기본값 차이를 가장 확실히 제거하는 방법입니다.
  2. 2automatic 변수는 선언 시 초기화하지 말고 본문에서 할당. Cummings 가이드(SNUG).
  3. 3함수는 순수 계산(combinational)으로만 사용. 상태가 필요하면 함수 바깥의 레지스터로 외부화합니다.
  4. 4재귀 깊이는 컴파일 타임 상수로 제한. parameter로 받은 N에 한해 합성 가능.
  5. 5fork-join 환경 task는 automatic 필수. Vivado UG901 p.245 권고 사항.
  6. 6UVM 클래스 메서드는 자동으로 automatic. 명시는 선택이지만 가독성을 위해 적는 표준도 일반적.

🧠 한 줄 코딩 표준: "RTL용 모든 task/function에는 automatic을 붙이고, 함수는 순수 계산만, 상태는 레지스터로 외부화한다." — 이 한 줄만 지켜도 시뮬과 합성의 90% 불일치는 사라집니다.

6. 결론

SystemVerilog의 automatic은 소프트웨어의 스택 기반 재진입성 개념을 HDL에 이식한 장치입니다. IEEE 1800-2017 §6.21이 정의한 대로 스코프 진입마다 재할당, 종료 시 소멸되며, Synopsys·Xilinx·Intel 모든 주요 합성기가 지원합니다.

다만 하드웨어에는 스택이 없으므로 합성기는 unrolling과 임시 와이어로 매핑하며, 재귀 깊이는 반드시 컴파일 타임 상수여야 한다는 제약이 따릅니다.

실무에서는 시뮬레이션-합성 불일치를 막기 위해 모든 RTL용 task/function에 automatic을 명시하고, 선언 시 초기화를 피하며, 상태 보존은 함수 바깥의 레지스터로 외부화하는 코딩 표준을 채택하는 것이 정답입니다. IEEE 표준, Cummings의 SNUG 가이드, Xilinx UG901, Intel Quartus 가이드, Synopsys DC 문서 모두 이 결론에서 일관됩니다.

참고 자료

본 글은 SystemVerilog 표준 및 주요 EDA 벤더 공식 문서를 기반으로 한 기술 정리이며, 특정 프로젝트의 합성 결과는 사용 중인 툴 버전·라이브러리·제약 파일에 따라 달라질 수 있습니다.
📄 Raw Data
# [최종 보고서] SystemVerilog `automatic` 키워드: 생명주기, 합성 가능성, 그리고 설계 가이드

## 1. 연구 배경과 문제 의식

SystemVerilog는 Verilog의 정적(static) 변수 모델을 유지하면서도, 클래스 기반 검증 환경(UVM)과 재진입 가능한(reentrant) 서브루틴을 지원하기 위해 **변수 생명주기(Variable Lifetime)** 개념을 도입했다. 그 핵심에 있는 키워드가 바로 `automatic`이다. 본 보고서는 다음 세 가지 질문에 답한다.

1. `automatic`은 어떻게 동작하는가 (메모리 할당과 생명주기 관점)?
2. 합성 가능한가, 가능하다면 어떤 하드웨어로 매핑되는가?
3. 실무에서 어떤 함정이 있고, 어떤 가이드를 따라야 하는가?

---

## 2. 기초 개념: Static vs Automatic Lifetime

### 2.1 IEEE 1800-2017 표준 정의

IEEE 1800-2017 표준(Section 6.21 *Scope and lifetime*)은 두 생명주기를 다음과 같이 정의한다.

- **Static lifetime (§6.21.1):** "모듈, 프로그램, 인터페이스, 태스크, 함수 외부에 선언된 변수는 static이며 프로그램 실행 전체에 걸쳐 존재한다."
- **Automatic lifetime (§6.21.2):** "automatic 변수는 **스코프에 진입할 때마다 재할당되며 스코프 종료 시 소멸한다**(reallocated on each entry to the scope ... destroyed on exit)."

즉 `automatic`은 소프트웨어의 스택 프레임(stack frame)과 동일한 개념이며, 호출(call)마다 독립된 메모리 인스턴스를 갖는다.

### 2.2 기본값(Default Lifetime) 규칙

| 선언 위치 | 기본 생명주기 |
|---|---|
| `module` / `interface` / `program` / `package` 내부 | **static** |
| `class` 메서드 내부 변수 | **automatic** |
| `for` 루프의 루프 변수(`for (int i ...)`) | **automatic** |
| `task` / `function` 내부 변수 | **선언된 task/function의 lifetime을 따름** (기본 static) |

이 기본값 규칙 때문에 RTL 설계 단계에서 `task`나 `function`을 정의할 때 무의식적으로 static 동작을 채택하게 되며, 이것이 후술할 race condition과 재귀 실패의 근본 원인이 된다.

---

## 3. 동작 분석: 무엇이 달라지는가

### 3.1 초기화 시점

- **Static:** 시뮬레이션 타임 0에서 단 한 번 초기화.
- **Automatic:** 스코프 진입 시점마다 매번 초기화(또는 미초기화 상태로 할당).

### 3.2 재진입성과 데이터 무결성

`fork ... join`이나 다중 인스턴스 호출 환경에서 static 변수는 모든 호출이 동일한 메모리를 공유하므로 **race condition**이 발생한다. Clifford Cummings는 *SystemVerilog Coding Standard*(2020)에서 이를 "scratchpad memory" 비유로 설명하며 "값 보존이 필요하면 반드시 static, 매 호출 독립이 필요하면 반드시 automatic"이라고 못 박는다(Sunburst Design Paper).

```systemverilog
// 안전: 동시에 호출되어도 temp가 격리됨
task automatic do_calc(input int a, output int b);
    int temp;            // 호출마다 독립 인스턴스
    temp = a + 5;
    #10;
    b = temp * 2;
endtask
```

위 코드에서 `automatic`을 제거하면 두 프로세스가 동시에 `do_calc`을 호출할 때 `temp`가 공유되어 결과가 오염된다.

---

## 4. 합성 가능성(Synthesizability) 검토

핵심 질문은 "스택이 없는 하드웨어가 어떻게 automatic을 구현하는가"이다.

### 4.1 매핑 원리: 풀기(Unrolling)와 임시 와이어

EDA 합성기는 물리적 스택을 만들지 않는다. 대신 다음과 같이 처리한다.

- **임시 신호화:** `automatic` 변수는 조합 회로 내부의 임시 노드(wire)로 매핑된다.
- **호출 사이트 복제(Unrolling):** 동일 함수가 여러 곳에서 호출되면 합성기는 각 호출 사이트마다 독립된 로직 게이트 군을 복제 배치한다.
- **재귀의 정적 전개:** 재귀 호출은 컴파일 타임에 깊이가 고정될 때에 한해 직렬/병렬 회로로 펼쳐진다.

### 4.2 벤더별 지원 현황

| 벤더/툴 | 지원 상태 | 근거 |
|---|---|---|
| **Synopsys Design Compiler** | Task/Function의 automatic 완전 지원. 재귀는 깊이 제한 또는 unroll 가능 시에만. | *Synopsys Design Compiler User Guide, T-2022.03* |
| **Xilinx (AMD) Vivado** | 공식 지원. UG901은 "동일 모듈 내 두 위치에서 동시 호출되는 task/function에는 `automatic`이 **필수**"라고 명시 (p.245). | [UG901, v2023.2](https://docs.amd.com/r/en-US/ug901-vivado-synthesis/SystemVerilog-Tasks-and-Functions) |
| **Intel Quartus Prime Pro/Std** | "Quartus Prime supports automatic variables in tasks and functions." | *Intel Quartus Prime Pro Synthesis User Guide, v23.4* |

특히 Vivado는 **시뮬레이션-합성 불일치를 줄이기 위해 task/function을 내부적으로 automatic처럼 취급**하는 경향이 있다. 시뮬레이터의 기본값(static)과 합성기의 사실상 기본값이 다를 수 있다는 점이 핵심 함정 중 하나다.

### 4.3 재귀(Recursion)의 합성 조건

재귀가 합성 가능하려면 **재귀 깊이가 컴파일 타임에 상수로 결정**되어야 한다. 입력 신호 의존적 재귀(dynamic recursion)는 Synopsys DC에서 `Error: [ELAB-311] Task/Function is too complex to unroll` 류의 에러로 거부된다. Vivado 또한 자원이 기하급수적으로 증가하는 깊은 재귀를 사실상 합성 불가로 처리한다.

```systemverilog
module factorial_module #(parameter N = 4) (
    output logic [31:0] out
);
    function automatic int factorial(int n);
        if (n <= 1) return 1;
        else        return n * factorial(n - 1);
    endfunction

    assign out = factorial(N);  // N이 상수이므로 멀티플라이어 체인으로 unroll
endmodule
```

`N`이 parameter(컴파일 타임 상수)이므로 위 코드는 곱셈기 체인으로 풀려 합성된다. `N`이 입력 포트라면 합성은 실패한다.

---

## 5. 알려진 함정(Pitfalls)과 시뮬레이션-합성 불일치

### 5.1 선언 시점 초기화 함정

```systemverilog
function automatic int foo();
    int a = 5;   // 위험
    ...
endfunction
```

- **시뮬레이터:** 호출마다 `a`를 5로 초기화.
- **일부 합성기:** 초기화 구문을 상수로 오인하거나 무시할 수 있음.
- **Cummings의 가이드(SNUG 2002/2020):** "선언과 동시에 automatic 변수를 초기화하지 말 것. 별도의 할당문을 사용할 것."

### 5.2 `always_ff` 내부에서의 오용

`automatic` 변수는 본질적으로 조합 임시 저장소이다. `always_ff` 내부에서 automatic 변수의 값을 다음 클럭까지 유지하려 하면 의도치 않은 래치/플립플롭이 합성되거나 합성 에러가 발생한다. 상태 보존이 필요하면 **`logic` 레지스터 + `always_ff` 조합**으로 명시적으로 모델링해야 한다.

### 5.3 시뮬레이션-합성 기본값 차이

- 시뮬레이터: task/function 기본 lifetime = **static**.
- Xilinx Vivado: 사실상 **automatic처럼 취급**(UG901 페이지 참조).

이 비대칭은 시뮬레이션에서 멀쩡히 동작하다 실리콘에서 다르게 동작하는 전형적 함정이다. 따라서 **모든 task/function에 `automatic`을 명시**하는 것이 양쪽 동작을 일치시키는 가장 확실한 방법이다.

---

## 6. 권장 가이드라인 (Best Practices)

1. **모든 합성용 `task`/`function`에 `automatic`을 명시한다.** 시뮬레이션(static 기본)과 합성기(automatic처럼 처리) 간 동작 차이를 제거하는 가장 안전한 선택이다.
2. **`automatic` 변수는 선언 시 초기화하지 말고 본문에서 별도로 할당한다.** (Cummings, SNUG)
3. **함수는 순수 계산(combinational)으로만 사용한다.** 값 보존이 필요하면 함수 내부 static이 아니라 `always_ff` + 레지스터로 외부화한다.
4. **재귀 호출의 깊이는 반드시 컴파일 타임 상수에 의해 제한**되어야 한다. 입력 신호 의존 재귀는 합성 불가다.
5. **`fork...join`이나 동시 호출이 발생하는 task에는 `automatic`이 필수**(Vivado UG901 p.245: "required if a task or function is to be called concurrently from two locations").
6. **UVM 클래스 메서드는 기본 automatic**이므로 검증 환경에서는 명시할 필요가 없지만, 가독성을 위해 명시하는 코딩 표준도 일반적이다.

---

## 7. 결론

SystemVerilog의 `automatic`은 소프트웨어의 스택 기반 재진입성 개념을 HDL에 이식한 장치다. IEEE 1800-2017 §6.21이 명확히 규정한 대로, **스코프 진입마다 재할당, 종료 시 소멸**되는 변수이며, Synopsys/Xilinx/Intel 등 모든 주요 합성기가 이를 지원한다. 다만 하드웨어에는 스택이 없으므로 합성기는 unrolling과 임시 와이어로 매핑하며, **재귀 깊이는 컴파일 타임 상수**여야 한다는 제약이 따른다. 실무에서는 시뮬레이션-합성 불일치를 막기 위해 모든 RTL용 task/function에 `automatic`을 명시하고, 선언 시 초기화를 피하며, 상태 보존은 함수 바깥의 레지스터로 외부화하는 코딩 표준을 채택할 것을 권장한다.

(라운드 1~2 사이에서 자료 간 모순은 관찰되지 않았다. IEEE 표준, Cummings의 가이드, Xilinx/Intel/Synopsys 문서는 동작 정의·합성 지원 여부·재귀 제약에서 모두 일관된 입장을 보였다.)
---

## References

- [IEEE 1800-2017 Standard](https://ieeexplore.ieee.org/document/8299595)
- [Xilinx Vivado Synthesis Guide UG901](https://docs.amd.com/r/en-US/ug901-vivado-synthesis/SystemVerilog-Tasks-and-Functions)
- [Sunburst Design SystemVerilog Papers (Cliff Cummings)](http://www.sunburst-design.com/papers/)

댓글

이 블로그의 인기 게시물

Vim 9.2 릴리즈 총정리: 더 빠르고 강력해진 텍스트 편집의 제왕

폐쇄망 SoC 설계자를 위한 가볍고 빠른 Vim 최적화 가이드

에이전트 시대를 위한 터미널 cmux 가이드: 설치부터 AI 활용까지