2025년 12월 30일 화요일

오픈-소스 설계 툴이 사전 설치된 WSL 가상 디스크 이미지 배포 및 사용법

오픈-소스 설계 툴이 사전 설치된 WSL 가상 디스크 이미지 배포 및 사용법

목차:

1. 개요

2. WSL2 설치
    2-1. 가상화 기술 활성화
    2-2. 윈도우즈 기능 켜기/끄기
    2-3. WSL2  갱신 설치
    2-4. 우분투 리눅스 24.04 설치
    2-5. WSL 가상 디스크 경로변경
    2-6. WSL의 가상 디스크 옮기기
    2-7. WSL 기본 사용자 설정

3. 설계툴이 설치된 가상 디스크 사용
    3-1. 오픈-소스 툴이 설치된 가상 디스크 받기
    3-2. 가상 디스크 변경
    3-3. 외장 HDD 접근 제한

4. 예제 수행
    4-1. 우분투 터미널 열기
    4-2. 예제 디랙토리 복사
    4-3. 예제: pong_pt1

5. 맺음말

CC-BY-NC
by GoodKook, goodkook@gmail.com
https://groups.google.com/g/mychip-on-mydesk

--------------------------------------------------------------

1. 개요

오픈-소스 반도체 설계 도구들은 리눅스 운영체제 환경에서 실행된다. 따라서 "내 칩 제작 서비스"의 MPW를 통해 내 칩을 제작하려면 리눅스를 설치해야 한다. 리눅스 운영체제는 가벼워서 구형 PC에서도 무난하다.

[주] 15년전에 출시된 듀얼코어 i3-2xx0M 나 i5-2450M 급 CPU에 8기가바이트 RAM과 128기가 바이트 정도의 PC(노트북)에서 최신 리눅스 커널 6(우분투 24.04 등)를 설치하고 오픈-소스 반도체 설계 도구들과 FPGA 벤더의 도구(자일링스 비티스 2025.1, 알테라 쿼터스 24.1, 고윈 EDA)들을 무리없이 실행 시킬 수 있다. 설계 규모에 달렸으나 Artix-7, Cyclone-IV/V, GW-25A 급 FPGA들의 P&R을 무리없이 해낸다.

[주] 오픈-소스 EDA 도구들은 소스로 제공되므로 ARM 기반의 리눅스에서도 도구들을 빌드하여 반도체를 설계할 수 있다. 심지어 오픈-소스 컴퓨터 "라즈베리 파이 5(2W에서도 가능하다고 함)"에서 리눅스를 설치하고 "내 칩"을 설계한 경우도 있다. 아래 링크 참조하자. 이런 호환성을 갖추기까지 재능을 아낌없이 바쳐준 모든 이들에게 감사와 경의를 표한다.

[출처] 라즈베리파이5를 NVMe SSD로 부팅하고 오픈소스 반도체설계도구 설치해 보기|작성자 chosim1762[링크]

리눅스를 설치할 별도의 컴퓨터를 마련하지 못했다면 윈도우즈 10/11의 WSL(Windows Subsystem for Linux)을 통해 리눅스를 실행 시킬 수 있다. 비록 가상머신에서 실행 되지만 성능 저하는 거의 없이 리눅스 응용 프로그램들을 실행 시킬 수 있다. 여기에는 자일링스 비티스, 알테라 쿼터스등 리눅스용 배포판들도 포함된다.

새로산 컴퓨터에 운영체제의 직접 설치가 당연했던 시절이 있었지만 지금은 거의 가전 수준이 되어버려서 그런 경우는 거의 없다. 하지만 자유로운 배포를 허용하는 까닭에 리눅스를 포함한 오픈-소스 반도체 설계 도구 사용을 지원하는 회사는 흔치 않다. 물론 비용을 지불하면 서비스를 받을 수 있지만 다소 높다. "알아서 스스로"라는 오픈-소스의 개념이 전문가(또는 경험자)의 영역으로 받아들여지고 있어 아쉽다.

세상에 하나뿐인 "내 칩"을 설계하고 "공짜로" 제작하려면 어쨌든 리눅스와 설계 도구들을 설치해야 한다. 반도체 설계가 다소 복잡한 과정을 거치는 만큼 필요한 도구들도 여럿이다. 리눅스라는 운영체제조차 생소할 입문자는 반도체 설계도구들을 모두 "알아서" 준비하려면 어려움이 있다. 이 문서는 이를 해소하고자 윈도우즈 10/11의 WSL 가상 머신 환경에 리눅스와 설계 도구들을 모두 설치한 가상 디스크 이미지를 배포하고 사용법을 설명한다.

배포하는 가상 디스크 이미지에 설치된 내용은 아래와 같다.

    Linux: Ubuntu 24.04.1 [link]

    z3: Problem Solver [link]
    SDL2:  Simple Direct Layer [link]
    gsl: GNU Scientific Library [link]
    graywolf: GrayWolf Auto Placer [link]
    qrouter: Auto-Router [link]
    irsim: IRSim Switching Level Simulator [link]
    magic: VLSI Layout Tool [link]
    klayout: Layout Tool [link]
    netgen: NetGen Layout vs Schematic compare [link]
    ngspice42: SPICE simulator [link]
    xschem & GAW: XSchem Schematic entry tool [link] [link]
    systemC: SystemC C++ Class Library(IEEE Std. 1666-2023) [link]
    iverilog:  iVerilog HDL simulator [link]
    Verilator: Verilog to C++/SystemC converter [link]
    gtkwave: gtkWave Digital waveform viewer [link]
    yosys: Yosys RTL Synthesizer [link]
    QFlow: An Open-Source Digital Synthesis Flow [link]
    ETRI050 DK: ETRI 0.5um CMOS MPW Std-Cell Design Kit [link]

    Visual Studio Code for Linux [link]

오픈-소스 반도체 설계 도구 설치 준비물:

    Windows 10 또는 11이 설치된 PC*

        * i5 급 CPU와 RAM 4기가 바이트 정도의 저사양 노트북 PC에서도 WSL은 무리없이 작동한다.

    하드 디스크 용량: 128기가 바이트** 이상의 여유 공간 필요하다.

        ** 비티스 HLS와 쿼터스를 설치하는 경우의 용량이다. 단지 오픈-소스 설계 도구 만 설치하는 경우 64기가 바이트로도 충분하다.

노트북 PC에 용량이 부족하다면 외장 USB 하드디스크를 활용한다. 입문하는 단계에서는 주변에 노는 저장 매체를 활용 할 수 있다. USB 2.0 규격의 외장 저장 장치도 괜찮다. 마이크로 SD 카드 리더가 장착된 경우 128기가 바이트 마이크로 SD 칩을 사용해도 좋다. USB 메모리는 약간의 인내력이 필요하다. 처음 설치할 때 40기가 바이트 가량의 대용량 파일을 옮겨야 하므로 상당한 시간(1~2시간)이 걸린다는 점만 빼면 실사용에는 지장없다. 외장 저장매체를 새로 사야 한다면 USB 3.x 규격의 256기가 바이트 이상 용량을 가진 외장 하드 디스크를 추천한다. 마이크로 SD 칩의 경우 U3/Class10 이면 충분하다. 2025년말 현재 약 2만원 가량에 판매되는 제품이 있다.

WSL에 설치되는 리눅스는 기본적으로 명령줄 기반의 사용자 인터페이스다. 반도체 설계에 사용되는 설계 도구들 역시 문자기반 이거나 단순한 2D 그래픽으로 윈도우즈에 전혀 부담을 주지 않는다. 설치와 제거 또한 윈도우즈로부터 자유롭다. 윈도우즈와 얽히지 않고 언재든 재설치 할 수 있다. 단, 자신의 자료 백-업은 잊지말자.

[참고] WSL/Ubuntu 재설치 [링크]

2. WSL2 설치

2-1. 가상화 기술 활성화

요즘 CPU는 가상화(Virtualization)을 모두 지원 한다. 간혹 해당 기능을 꺼놓은 경우가 있다. '작업 관리자'에서 확인 할 수 있다.

만일 가상화 기능이 꺼져 있는 경우 컴퓨터의 BIOS 설정에서 가상화 기술(Virtualization Technology, VT-x) 항목을 활성화 한다.

2-2. 윈도우즈 기능 켜기/끄기

Windows 기능 켜기/끄기(Windows Features) 창을 열어 아래 두가지 기능을 켠다.

    - Windows 하위 시스템 리눅스 (Windows Subsystem for Linux)

    - 가상머신 플랫 폼(Virtual Machine Platform)

2-3. WSL2  갱신 설치

윈도우즈를 재 부팅 후 파워쉘(Windows Power Shell)을 관리자 권한으로 열어 아래 명령 실행한다.

    PS> wsl --update

    PS> wsl --set-default-version 2

[주] 윈도우즈 파워 쉘(Windows Power Shell)이 7.5 이하라면 최신 버젼을 설치한다. 

2-4. 우분투 리눅스 24.04 설치

마이크로소프트 스토어에서 Ubuntu를 검색하여 24.04.1 LTS 를 다운 받아 설치한다.

터미널 창에 우분투 리눅스의 기본 사용자를 지정하라는 프롬프트가 뜨면 아이디와 비밀번호를 입력한다. 아래 예는 기본 사용자 아이디를 mychip 으로 하였다. 비밀번호도 user name 과 동일하다.

    Please create a default UNIX user account.
    The username does not need to match your Windows username.
    For more information visit: https://aka.ms/wslusers

    Enter new UNIX username: mychip

    New password:
    Retype new password:

    passwd: password updated successfully

    Installation successful!

WSL에  우분투 리눅스의 설치가 성공적으로 완료됐다.

2-5. WSL 가상 디스크 경로변경

윈도우즈와 리눅스는 파일 시스템의 호환성이 없다. 리눅스는 가상 디스크(.vhdx)에 설치되고 네트워크 드라이브로 윈도우즈 파일 탐색기에 연결된다. 가상 디스크는 기본적으로 C: 디스크에 만들어 진다. 위치는 아래와 같다.

    %LocalAppData%\Packages\<Distribution_Package_Name>\LocalState\ext4.vhdx

설계 도구들을 설치하고 운용하다보면 가상 디스크의 크기가 증가한다. 오픈-소스 EDA 도구들과 아듀이노 IDE/CLI, FPGA 개발 도구들(Quartus, Vitis-HLS)을 모두 설치하면 120GByte를  넘긴다. 하드 디스크의 용량이 제한적인 랩-톱  컴퓨터를 사용한다면 USB 외장 HDD에 옮겨도 좋다. 리눅스 운용체제와 반도체 설계 도구들은 가볍기 때문에 USB 3.x 에 부착된 외장 HDD로도 충분히 작동한다. 약간의 인내심이 필요하긴 하다.

주의! 가상 디스크는 수많은 리눅스 파일들이 담겨 있는 대용량 파일이다. 파일관리의 안정성을 위해 외장 디스크는 반드시 NTFS로 포맷되어야 한다.

2-6. WSL의 가상 디스크 옮기기

외장 HDD 가 D: 로 할당 되었을 경우를 상정하고 설명한다. 

a. 파워 쉘  명령창을 열고 외장 HDD  에 WSL2 라는 폴더를 생성한다.

    C:\> d:

    D:\> mkdir WSL2

b. 아래 깃 허브에서 Move-WSL 스크립트를 내려 받는다.

    https://github.com/pxlrbt/move-wsl

zip 압축으로 받았다면 적당한 위치에 압축을 풀어 놓으면 move-wsl/move-wsl.ps1 가 있을 것이다.

c. 관리자 권한으로 파워 쉘을 열고 WSL을 중지 시킨 후 스크립트를 실행한다.

    PS> wsl --shutdown

    PS> cd move-wsl

    PS> .\move-wsl.ps1

만일 스크립트 실행 권한이 없다는 메시지를 보게 되면 다음과 같이 보안을 풀어준 후 스크립트를 다시 실행한다.

    PS> Set-ExecutionPolicy bypass

    PS> D:\WSL2\move-wsl> .\move-wsl.ps1

현재 설치된 WSL의 리눅스 배포판이 나열될 것이다. 옮길 리눅스를 선택한다.

    Getting distros...
    Select distro to move:

    1: Ubuntu-24.04

    1

옮겨갈 위치를 입력한다. 아래의 예는 외장 HDD의 드라이브가 D: 다.

    Enter WSL target directory:

    D:\WSL2

    Move Ubuntu-22.04 to "d:\WSL2"? (Y|n): Y

    Exporting VHDX to "d:\WSL2\Ubuntu-24.04.tar" ...
    Export in progress, this may take a few minutes..

    The operation completed successfully.

    Done!

가상 디스크를 옮긴 후 root로 로그인 될 경우 기본 사용자 변경 절차를 따른다.

2-7. WSL 기본 사용자 설정

WSL에 우분투 리눅스를 설치 후 터미널을 열었을 때 root 로 로그인 된다면 /etc/wsl.conf 파일을 vi 로 열어 아래의 내용을 추가해 준다.

    [user]
    default=mychip

    [interop]
    appendWindowsPath=false

[interop] 은 리눅스 환경 변수 PATH에 윈도우스 실행 경로를 덧붙이지 않도록 하기 위한 것이다.

3. 설계툴이 설치된 가상 디스크 사용

WSL의 리눅스가 설치된 가상 디스크의 기본 파일명은  ext4.vhdx 다. 위의 "가상 디스크 경로 변경" 절차에 따라 옮겨진 폴더(D:\WSL2)에 ext4.vhdx 가 있다. 이 가상 디스크 파일은 파일명을 바꿔 백-업 해 두거나 삭제해도 좋다.

3-1. 오픈-소스 툴이 설치된 가상 디스크 받기

리눅스와 오픈-소스 반도체 설계 도구들이 설치된 가상 디스크를 아래 링크에서 내려받는다.

    오픈-소스 툴이 설치된 WSL2용 가상 디스크 받기[링크]

압축된 파일은 Archive/ext4_mychip.zip 로서 용량이 16.5기가 바이트에 달한다. 네트워크의 사정에 따라 1시간은 족히 걸릴 것이다. "내 책상 위에서 내 칩(My Chip on My Desk)"을 설계할 꿈을 꾸면서 여유를 가지고 기다린다. 도구들이 미리 설치된 가상 디스크 파일은 "내 칩 제작 서비스"/디자인 킷 사용자 그룹 회원에게 제공된다. 아래 링크의 사용자 그룹에서 신청하면 가입할 수 있다.

    "내 칩 제작 서비스"/"반도체 설계 교실" 오픈-소스 디자인 킷 사용자 그룹
    MyChip-on-MyDesk [link]

[주] 오픈-소스 설계 도구들은 디자인 킷의 깃허브 저장소에서 받아 개별적으로 설치 할 수 있다.

    ETRI 0.5um CMOS MPW Std-Cell Design Kit [link]

내려받은 압축 파일 ext4_mychip.zip 을 앞서 ext4.vhdx 가 옮겨갔던 디렉토리에 푼다. 가상 디스크의 파일명은 ext4_mychip.vhdx로 크기는 약 44기가 바이트 가량이다.

3-2. 가상 디스크 변경

WSL이 사용할 가상 디스크를 오픈-소스 도구들이 설치된 가상 디스크로 변경한다. 레지스트리에서 아래 항목을 찾는다.

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Lxss]

[UUID] 키 아래에 BasePath, VhdFileName 키 값을 변경하면 내려받아 풀어놓은 가상 디스크 파일을 사용할 수 있다. 외장 HDD의 D:\WSL2 경로에 가상 디스크 파일명을 ext4_mychip.vhdx 로 변경한 예는 아래와 같다.

3-3. 외장 HDD 접근 제한

윈도우즈 파일 탐색기는 WSL의 가상 디스크를 원격 연결 한다. WSL의 가상 디스크를 외장 HDD로 옮긴 후에 아래와 같은 윈도우즈 파일 탐색기 오류가 나는 경우가 발생한다.

 NTFS의 보안 기능으로 인해 외장 HDD에 접근 할 수 있는 권한이 제한되어 있어서 발생한다. 외장 HDD의 보안 속성을 모든 권한으로 바꿔준다.

4. 예제 수행

오픈-소스 반도체 설계 도구의 설치를 마쳤으면 예제를 수행해보자.

4-1. 우분투 터미널 열기

리눅스의 사용자 인터페이스의 기본은 명령줄이다. 우분투 터미널을 열면 아래와 같은 명령줄 프롬프트가 나타난다.

mychip@DESKTOP-XXXXX:~$

사용자 계정명은 mychip, 리눅스 서버 이름은 DESKTOP-XXXXX, 현재 위치한 디렉토리는 ~ 다. ~ 는 사용자의 홈 디렉토리를 뜻한다. 파일 시스템에서 사용자의 정식 경로명은 /home/mychip 이다. $ 는 리눅스 배쉬 쉘의 프롬프트 문자다.

4-2. 예제 디랙토리 복사

미리 받아놓은 디자인 킷의 예제를 적당한 위치에 복사한다. 편의상 작업 디렉토리를 MyChip_Work로 한다.

~$ mkdir MyChip_Work

~$ cd MyChip_Work

~/MyChip_Work$ cp -r ~/ETRI050_DesignKit/Projects .

cp 는 복사(copy) 명령 cp 에 -r 옵션을 붙였다. 하위 디렉토리까지 모두 복사해온다.

~/MyChip_Work$ cd Projects

~/MyChip_Work/Projects$ ll

    total 16
    drwxr-xr-x 4 mychip mychip 4096 Dec 30 12:43 .
    drwxr-xr-x 3 mychip mychip 4096 Dec 30 12:43 ..
    drwxr-xr-x 6 mychip mychip 4096 Dec 30 12:43 HLS
    drwxr-xr-x 7 mychip mychip 4096 Dec 30 12:43 RTL

4-3. 예제: pong_pt1

디렉토리 Projects 에 HLS와 RTL 이 있다. 각각 고위합성 예제 HLS와 베릴로그 예제 RTL 이다. 아직 HLS 도구들을 설치를 하기 전 이므로 RTL 디렉토리로 간다.

~/MyChip_Work/Projects$ cd RTL

~/MyChip_Work/Projects/RTL$ ll

    total 28
    drwxr-xr-x 7 mychip mychip 4096 Dec 30 12:43 .
    drwxr-xr-x 4 mychip mychip 4096 Dec 30 12:43 ..
    drwxr-xr-x 6 mychip mychip 4096 Dec 30 12:43 ALU8_Mult
    drwxr-xr-x 7 mychip mychip 4096 Dec 30 12:43 apple_1
    drwxr-xr-x 7 mychip mychip 4096 Dec 30 12:43 CPU_6502
    drwxr-xr-x 7 mychip mychip 4096 Dec 30 12:43 FIR_PE
    drwxr-xr-x 6 mychip mychip 4096 Dec 30 12:43 pong_pt1

여러 예제 중 1인 탁구 게임을 수행해 본다.

~/MyChip_Work/Projects$ cd pong_pt1

~/MyChip_Work/Projects/RTL/pong_pt1$ ll

    total 68
    drwxr-xr-x 6 mychip mychip  4096 Dec 30 12:43 .
    drwxr-xr-x 7 mychip mychip  4096 Dec 30 12:43 ..
    drwxr-xr-x 4 mychip mychip  4096 Dec 30 12:43 emulation
    drwxr-xr-x 6 mychip mychip  4096 Dec 30 12:43 ETRI050
    drwxr-xr-x 2 mychip mychip  4096 Dec 30 12:43 pong_pt1
    drwxr-xr-x 3 mychip mychip  4096 Dec 30 12:43 simulation
    -rw-r--r-- 1 mychip mychip   530 Dec 30 12:43 env_settings
    -rw-r--r-- 1 mychip mychip 22319 Dec 30 12:43 HOW-TO.txt
    -rw-r--r-- 1 mychip mychip 13777 Dec 30 12:43 Makefile

Makefile이 있다. 반도체 설계 플로우의 모든 과정이 여기에 기술되있다. Makefile은 개발자라면 평생 끼고 살게될 make 유틸리티의 스크립트다. 지금은 맛보기 이므로 따라해보자.

먼저 환경 설정,

~/MyChip_Work/Projects/RTL/pong_pt1$ source env_settings

#*******************************************************************
#* Environment setting for RTL, Co-Simulmatio/Emulation & ETRI050
#*******************************************************************

Setting Environment variables as follows;
    PROJECT_DIR=/home/mychip/MyChip_Work/Projects/RTL/pong_pt1
    TOP_MODULE=pong_pt1
    HW_STYLE=NONE
    MODE=CA
    MI=PI_PICO

~/MyChip_Work/Projects/RTL/pong_pt1$ make

    RTL Project: pong_pt1
        TOP_MODULE=pong_pt1 VCD_TRACE=[YES]|NO make co-sim
        TOP_MODULE=pong_pt1 make wave

        make emulation
        make ETRI050

    CC BY-NC, by GoodKook, goodkook@gmail.com

이제 make 유틸리티를 사용하여 예제를 수행할 준비가 되었다. 아래와 같이 따라해보자.

~/MyChip_Work/Projects/RTL/pong_pt1$ make co-sim


베릴로그 RTL 기능 시뮬레이션이다. 초당 10여 프레임(64x128 픽셀)씩 생성되는 그래픽 게임기의 화면을 만들어내는 디지털 회로의 시뮬레이션을 디지털 파형으로 확인하기는 불가능하다. 그래픽으로 확인한다. 탁구대와 공의 움직임을 볼 수 있다.

베릴로그 RTL을 ETRI050 노드로 합성,

~/MyChip_Work/Projects/RTL/pong_pt1$ make ETRI050

~/MyChip_Work/Projects/RTL/pong_pt1$ make synth_ETRI050

네트리스트 타이밍 시뮬레이션,

~/MyChip_Work/Projects/RTL/pong_pt1$ make sim_ETRI050

기능 시뮬레이션에 비해 매우 느리게 작동할 것이다. 이 시뮬레이션을 수행 하는 중에 디지털 동작을 VCD로 기록한다. 방대한 량이 만들어 지게 되므로 너무 오랫동안 시뮬레이션을 수행하지 않도록한다.  VCD 파형을 보려면,

~/MyChip_Work/Projects/RTL/pong_pt1$ make -C ETRI050/simulation wave

시뮬레이션 검증이 완료되었으므로 이제 본격적으로 도면 생성이다. 표준 셀 자동 배치와 배선,

~/MyChip_Work/Projects/RTL/pong_pt1$ make pnr_ETRI050

레이아웃 GDS를 보자.

~/MyChip_Work/Projects/RTL/pong_pt1$ make layout_ETRI050

5. 맺음말

소프트웨어 개발에 사용되는 각종 컴파일러 도구들의 자동화는 눈부시다. 반도체 설계 기술 역시 엄청난 발전을 거듭하여 컴퓨팅 언어로 기술된 기능을 디지털 반도체 회로로 바꿔내는 일은 거의 자동화 되었다. 반도체는 한번 공정이 이뤄져 칩이 생산되면 수정은 불가하다. 비용이 많이 들고 제작기간이 긴 반도체 부품은 공정이 시작되기 전에 엄청난 검증과정을 거쳐야 한다. 무엇을 기술할 것인지 어떻게 검증할 것인지에 대한 답을 해야한다. "반도체 설계 교실"에서 이에 대한 답을 찾아볼 것이다.



2025년 12월 8일 월요일

[실습] HLS/basic_loops

[실습] HLS/basic_loops

목차:

1. 실습 개요

2. 환경 설정

3. C 시뮬레이션(언-타임드)

4. 고위합성(HLS)
     4-1. Vitis-HLS 고위합성(HLS)
     4-2. 고위 합성으로 얻은 RTL
     4-3. HLS 결과 보기

5. RTL 기능 시뮬레이션(Functional Simulation)
     5-1. HDL(Verilog RTL)와 SystemC TB
     5-2. 공동 시뮬레이션(Co-Simulation)
     5-3. 디지털 시뮬레이션 결과 파형

6. ETRI050 노드
    6-1. 합성 환경
    6-2. RTL 합성
    6-3. 합성 후 네트 시뮬레이션
    6-4. 표준 셀 자동 배치와 배선


CC-BY-NC
by GoodKook, goodkook@gmail.com

-----------------

1. 실습 개요

HLS(High Level Synthesis)와 ETRI050 노드 설계 플로우  학습

    - C++ 로 기술된 누산(accumulation) 알고리즘을 RTL 하드웨어 언어로 합성

    - 소프트웨어 함수(언-타임드, Un-Timed)와 하드웨어 모듈(타임드, Timed)의 외형 차이

    - HLS의 디지털 하드웨어 인터페이스: 모듈의 핸드 쉐이크 및 동기 메모리 인터페이스

    - RTL하드웨어 언어(Verilog)와 C++ 타임드 테스트벤치(SystemC)의 공동 시뮬레이션

    - "내 칩 제작 서비스"/ETRI050 노드: RTL 합성, 자동 배치 배선 그리고 사인오프 검사

    - 베릴로그 VPI: RTL 합성 후 네트리스트 타이밍 시뮬레이션


C++: basic_loops.cpp

// Filename: basic_loop.cpp
#include "basic_loops.h"

dout_t basic_loops(din_t A[N_MEM])
{
    dout_t out_accum = 0;
    dsel_t x;   // Address of Ext. Mamory

    LOOP_1:
    for (x = 0; x < N_MEM; x++)
        out_accum += A[x];

    return out_accum;
}

헤더: basic_loops.h

// Filename: basic_loop.h

#ifndef _BASIC_LOOPS_H_
#define _BASIC_LOOPS_H_

// Vitis HLS no longer support SystemC after 2020.1
// Fortunately, bit-wised ap_(u)int<> type is compatible with sc_(u)int<>

#if VM_SC==1    // SystemC ---------------------------------

#include "systemc.h"

typedef sc_int<8>   din_t;
typedef sc_int<13>  dout_t;
typedef sc_uint<5>  dsel_t; // Address of Ext. Memory

#else           // Vitis-HLS -------------------------------

#include "ap_int.h"

typedef ap_int<8>   din_t;
typedef ap_int<13>  dout_t;
typedef ap_uint<5>  dsel_t; // Address of Ext. Memory

#endif

#define N_MEM   10

dout_t basic_loops(din_t A[N_MEM]);

#endif

실습 소스: [깃 허브]

2. 환경 설정

$ cd ~/ETRI050_DesignKit/Projects/HLS/basic_loops

$ tree

  .
  ├── c_untimed
  │   ├── basic_loops.cpp
  │   ├── basic_loops.h
  │   ├── basic_loops_TB.cpp
  │   └── Makefile
  ├── simulation
  │   ├── Makefile
  │   ├── sc_basic_loops_TB.cpp
  │   ├── sc_basic_loops_TB.h
  │   └── sc_main.cpp
  ├── emulation
  │   ├── PSCE-MI
  │   │   ├── Ebasic_loops_CA
  │   │   │   ├── Ebasic_loops_CA.ino
  │   │   │   ├── PinMap_A7_100T.h
  │   │   │   ├── PinMap_TANG_25K.h
  │   │   │   ├── PSCE_APIs.cpp
  │   │   │   ├── PSCE_APIs.h
  │   │   │   ├── PSCE_Config.h
  │   │   │   └── PSCE_Splash.h
  │   │   └── Makefile
  │   ── PSCE-TRANS
  │      └── Altera_Cmd
  │          ├── basic_loops_wrapper_II.tcl
  │          ── basic_loops_wrapper_I.tcl
  │          └── Makefile
  │   ├── basic_loops_wrapper.v
  │   ├── Ebasic_loops.h
  │   ── Makefile
  ├── ETRI050
  │   ├── chip_top
  │   │   ├── ETRI050_CMOS.lyp
  │   │   └── Makefile
  │   ├── layout
  │   │   ├── basic_loops.cel2
  │   │   ├── basic_loops.par
  │   │   ├── ETRI050_CMOS.lyp
  │   │   └── Makefile
  │   ── simulation
  │      ├── basic_loops_TB.v
  │      ├── Makefile
  │      ├── sc_basic_loops_TB.h
  │      ├── vpi_basic_loops_tb.cpp
  │      ├── vpi_basic_loops_tb_exports.h
  │      ├── vpi_basic_loops_tb_ports.h
  │      └── vpi_stub.cpp
  │   ├── Makefile
  │   ├── project_vars.sh
  │   ├── qflow_exec.sh
  │   ── qflow_vars.sh
  ├── Makefile
  ├── env_settings
  └── Vitis-HLS.tcl

$ source env_settings

  #****************************************************************
  #* Environment setting for HLS, Co-Simulmatio/Emulation & ETRI050
  #****************************************************************
  Setting Environment variables as follows;
    PROJECT_DIR=~/ETRI050_DesignKit/Projects/HLS/basic_loops
    TOP_MODULE=basic_loops
    HW_STYLE=HW_STYLE
    MODE=CA
    MI=DUE_NORMAL

3. C 시뮬레이션(언-타임드)

pwd

  ~/ETRI050_DesignKit/Projects/HLS/basic_loops

make

  Vitis-HLS Project: basic_loops
    TOP_MODULE=basic_loops HW_STYLE=HW_STYLE make csim
    TOP_MODULE=basic_loops HW_STYLE=HW_STYLE make csynth
    TOP_MODULE=basic_loops make view_rpt
    TOP_MODULE=basic_loops make co-sim
    TOP_MODULE=basic_loops make wave

    make emulation
    make ETRI050

$ make csim

  TOP_MODULE=basic_loops HW_STYLE=HW_STYLE make -C ./c_untimed build
  make[1]: Entering directory './c_untimed'
  clang++ -I/opt/systemc/include -L/opt/systemc/lib \
        -o basic_loops_TB \
        -DHW_STYLE_SC \
        -DVM_SC=1 \
        ./basic_loops.cpp ./basic_loops_TB.cpp \
        -lsystemc
  make[1]: Leaving directory './c_untimed'

  TOP_MODULE=basic_loops make -C ./c_untimed run
  make[1]: Entering directory './c_untimed'
  ./basic_loops_TB

        SystemC 3.0.2-Accellera --- Dec  8 2025 10:15:05
        Copyright (c) 1996-2025 by all Contributors,
        ALL RIGHTS RESERVED

    Sum=45
  make[1]: Leaving directory './c_untimed'

4. 고위합성(HLS)

HLS 도구는 자일링스(Xilinx)의 비티스HLS(Vitis-HLS)다. C++ 코드를 합성 가능한 RTL 하드웨어 언어(베릴로그 또는 VHDL)로 합성해 준다. 기능 합성은 물론 인터페이스 합성을 수행한다. 비티스HLS 는 분석기(RTL analyzer)등 일부를 제외하고 전 기능 무료다. 합성으로 생성된 RTL 모델은 자일링스 사의 FPGA 구조에 최적화 되어 있다고 하지만 매우 보편적인 코딩 스타일을 따른다. ASIC은 물론 타사 FPGA에서도 큰 손해 없이 표준 하드웨어 언어 설계 플로우(시뮬레이션 및 합성기)를 따라 포팅 가능하다. 자사 FPGA로 타게팅 했을 경우 타이밍 분석과 최적화가 있을 뿐 합성된 RTL은 표준의 하드웨어 언어로 기술되어 있다. 자일링스 사의 디지털 회로 개념과 알테라의 디지털 회로 또는 ETRI050의 디지털 회로가 다를리가 없다. 높은 추상화 수준의 컴퓨팅 언어를 사용하는 이유는 이전가능(portability)이다. 

4-1. Vitis-HLS 고위합성

$ make csynth

  vitis-run --mode hls --tcl Vitis-HLS.tcl

  ****** vitis-run v2025.1 (64-bit)
  **** SW Build 6137779 on 2025-05-21-18:10:03
  **** Start of session at: Mon Dec  8 16:17:55 2025
    ** Copyright 1986-2022 Xilinx, Inc. All Rights Reserved.
    ** Copyright 2022-2025 Advanced Micro Devices, Inc.
       All Rights Reserved.

  **** HLS Build v2025.1 6135595

  Sourcing Tcl script './Vitis-HLS.tcl'
   ..........

VitisHLS 스크립트: Vitis-HLS.tcl

append PROJECT_NAME $env(TOP_MODULE)
puts $PROJECT_NAME
append HW_STYLE "-D" $env(HW_STYLE)
puts $HW_STYLE
append CPP_FILES $env(CPP_FILES)
puts $CPP_FILES

open_project "$PROJECT_NAME"
set_top "$PROJECT_NAME"

add_files "$CPP_FILES" -cflags "$HW_STYLE"

open_solution "hls_component" -flow_target vivado

set_part {xa7a100tcsg324-2I}

create_clock -period 1000 -name default

csynth_design

write_ini ./$PROJECT_NAME.cfg

exit

$ ll

  total 60
  drwxr-xr-x 8 mychip mychip  4096 Dec  8 16:18 .
  drwxr-xr-x 6 mychip mychip  4096 Oct 27 22:22 ..
  drwxr-xr-x 3 mychip mychip  4096 Dec  8 16:18 basic_loops
  drwxr-xr-x 2 mychip mychip  4096 Dec  8 16:17 c_untimed
  drwxr-xr-x 4 mychip mychip  4096 Dec  8 15:40 emulation
  drwxr-xr-x 7 mychip mychip  4096 Dec  8 15:42 ETRI050
  drwxr-xr-x 2 mychip mychip  4096 Dec  8 16:17 logs
  drwxr-xr-x 2 mychip mychip  4096 Dec  8 15:41 simulation
  -rw-r--r-- 1 mychip mychip   173 Dec  8 16:18 basic_loops.cfg
  -rw-r--r-- 1 mychip mychip   540 Oct 27 22:22 env_settings
  -rw-r--r-- 1 mychip mychip 13940 Oct 27 22:22 Makefile
  -rw-r--r-- 1 mychip mychip   425 Oct 27 22:22 Vitis-HLS.tcl

$ cd basic_loops

$ tree

  .
  └── hls_component
      ├── ......
      ├── impl
      │   ── ......
      └── syn
        ├── report
        │   ├── basic_loops_csynth.rpt
        │   ├── ......
        │   ├── csynth.rpt
        │   └── csynth.xml
        ├── verilog
        │   ├── basic_loops_flow_control_loop_pipe.v
        │   └── basic_loops.v
        └── vhdl
            ├── basic_loops_flow_control_loop_pipe.vhd
            └── basic_loops.vhd

4-2. 고위 합성으로 얻은 RTL

module basic_loops (
    input   ap_clk,
    input   ap_rst,
    input   ap_start,
    output   ap_done,
    output   ap_idle,
    output   ap_ready,
    output  [3:0] A_address0,
    output   A_ce0,
    input  [7:0] A_q0,
    output  [12:0] ap_return
);

언-타임드 모델(C++ 의 함수)에서 없던 신호들이 있다는 점에 주목한다. 하드웨어 언어로 RTL(Register Transfer Level)에서 기술된 하드웨어는 클럭과 입출력의 신호들의 비트 단위로 상세히 기술되었다.

4-3. HLS 결과 보기

계산을 시작하여 마칠 때 까지 소요되는 클럭의 수(Latency Clcles)와 하드웨어 인터페이스에 주목한다. 하드웨어 인터페이스는 모듈의 핸드웨이크와 동기식 메모리가 있다.

$ make view_report

  ......

  + Latency:
    * Summary:

    +----------------+-------------+-----------+--------------------+
    |Latency (cycles)| (absolute)  |  Interval | Pipeline           |
    |  min   |  max  | min  | max  | min | max |   Type             |
    +--------+-------+------+------+-----+-----+--------------------+
    |      12|     12|12.0us|12.0us|   10|   10|loop auto-rewind stp|
    |        |       |      |      |     |     |  (delay=0 clock(s))|
    +--------+-------+------+------+-----+-----+--------------------+

  ......

  ================================================================
  == Interface
  ================================================================
  * Summary:
  +------------+-----+-----+------------+--------------+------------+
  |  RTL Ports | Dir | Bits|  Protocol  | Source Object|  C Type    |
  +------------+-----+-----+------------+--------------+------------+
  |ap_clk      |   in|    1|  ap_ctrl_hs|   basic_loops|return value|
  |ap_rst      |   in|    1|  ap_ctrl_hs|   basic_loops|return value|
  |ap_start    |   in|    1|  ap_ctrl_hs|   basic_loops|return value|
  |ap_done     |  out|    1|  ap_ctrl_hs|   basic_loops|return value|
  |ap_idle     |  out|    1|  ap_ctrl_hs|   basic_loops|return value|
  |ap_ready    |  out|    1|  ap_ctrl_hs|   basic_loops|return value|
  |ap_return   |  out|   13|  ap_ctrl_hs|   basic_loops|return value|
  |A_address0  |  out|    4|   ap_memory|             A|       array|
  |A_ce0       |  out|    1|   ap_memory|             A|       array|
  |A_q0        |   in|    8|   ap_memory|             A|       array|
  +------------+-----+-----+------------+--------------+------------+

5. RTL 기능 시뮬레이션(Functional Simulation)

5-1. HDL(Verilog RTL)와 SystemC TB

HLS 로 얻은 RTL 베릴로그는 오픈-소스 도구 베릴레이터(Verilator)로 SystemC 타임드 모델로 변환 후 테스트 벤치에 물려 시뮬레이션한다. 컴퓨팅 언어로 디지털 회로의 행위를 모사한 기능적 시뮬레이션이다. 실제 디지털 회로가 아니므로 지연은 없다(Zero-Delay simulation). SystemC로 작성된 타임드 테스트벤치는 다음과 같다.

sc_basic_loops_TB.h

SC_MODULE(sc_basic_loops_TB)
{
    sc_clock                ap_clk;
    sc_signal<bool>         ap_rst;
    sc_signal<bool>         ap_start;
    sc_signal<bool>         ap_done;
    sc_signal<bool>         ap_idle;
    sc_signal<bool>         ap_ready;
    sc_signal<sc_uint<4> >  A_address0;
    sc_signal<bool>         A_ce0;
    sc_signal<sc_uint<8> >  A_q0;
    sc_signal<sc_uint<13> > ap_return;

    Vbasic_loops*    u_basic_loops; // Instantiate Verilated DUT

    sc_uint<8>      MEM_Dut[10];
    sc_int<8>       MEM_Ref[10];
    dout_t          DutOut;
    dout_t          RefOut;

    // Test utilities
    void Test_Gen();
    void Test_Mon();
    void Memory();

    SC_CTOR(sc_basic_loops_TB):
        ap_clk("ap_clk", 100, SC_NS, 0.5, 0.0, SC_NS, false)
    {
        SC_THREAD(Test_Gen);
        sensitive << ap_clk;

        SC_THREAD(Test_Mon);
        sensitive << ap_clk;

        SC_THREAD(Memory);
        sensitive << ap_clk;

        u_basic_loops = new Ebasic_loops("u_Ebasic_loops");
        u_basic_loops->ap_clk(ap_clk);
        u_basic_loops->ap_rst(ap_rst);
        u_basic_loops->ap_start(ap_start);
        u_basic_loops->ap_done(ap_done);
        u_basic_loops->ap_idle(ap_idle);
        u_basic_loops->ap_ready(ap_ready);
        u_basic_loops->A_address0(A_address0);
        u_basic_loops->A_ce0(A_ce0);
        u_basic_loops->A_q0(A_q0);
        u_basic_loops->ap_return(ap_return);
    }
};

sc_basic_loops_TB.cpp

#include "sc_basic_loops_TB.h"
#include "basic_loops.h"

// Cycle-Accurate Test Generator
void sc_basic_loops_TB::Test_Gen()
{
    ap_start.write(0);
    ap_rst.write(1);

    wait(ap_clk.posedge_event());
    wait(ap_clk.posedge_event());

    ap_rst.write(0);

    while(true)
    {
        wait(ap_clk.posedge_event());

        if (ap_ready.read())
            ap_start.write(false);  // Hold hardware, New test vector

        if (ap_idle.read())
        {                           // At hardware's IDLE state,
            for(int i=0; i<10; i++) // Generate new test vector
                MEM_Ref[i] = MEM_Dut[i] = (int8_t)rand();

            ap_start.write(true);   // Then, START hardware
        }
    }
}

// Cycle-Accurate Output Monitor

void sc_basic_loops_TB::Test_Mon()
{
    int test_count = 0;
    while(true)
    {
        wait(ap_clk.posedge_event());

        if (ap_done.read())
        {
            RefOut = basic_loops(MEM_Ref); // Un-Timed Result
            DutOut = ap_return.read();  // Hardware Result

            if ((dout_t)RefOut!=(dout_t)DutOut)
                cout << "Error[";
            else
                cout << "Pass [";
            cout << std::setw(3) << test_count++ << "]:";
            cout << "RefOut=" << std::setw(5) << (dout_t)RefOut;
            cout << " | ";
            cout << "DutOut=" << std::setw(5) << (dout_t)DutOut;
            cout << std::endl;

            if (test_count>100)  break;
        }
    }
    sc_stop();
}

// Synchronous Memory

void sc_basic_loops_TB::Memory()
{
    while(true)
    {
        wait(ap_clk.posedge_event());

        if (A_ce0.read())
            A_q0.write(MEM_Dut[(sc_uint<8>)A_address0.read()]);
    }
}

5-2. 공동 시뮬레이션(Co-Simulation)

추상화 수준(abstraction level) 격차가 있는 이종 언어 사이의 공동 시뮬레이션(Co-Simulation)

pwd

  ~/ETRI050_DesignKit/Projects/HLS/basic_loops

$ make co-sim

  TOP_MODULE=basic_loops HW_STYLE=HW_STYLE make -C simulation build

  make[1]: Entering directory '.../simulation'
  verilator --sc -Wno-WIDTHTRUNC -Wno-WIDTHEXPAND \
            --trace --timing --pins-sc-uint \
            --top-module basic_loops  --exe --build \
            -CFLAGS -g \
            -CFLAGS -I../../c_untimed \
            -CFLAGS -I/opt/systemc/include \
            -CFLAGS -DVCD_TRACE_TEST_TB \
            -CFLAGS -DVCD_TRACE_DUT_VERILOG \
            -CFLAGS -DHW_STYLE_SC \
            -LDFLAGS -lm -LDFLAGS -lgsl \
            ./basic_loops/hls_component/syn/verilog/*.v  \
            ../c_untimed/basic_loops.cpp \
            ./sc_main.cpp ./sc_basic_loops_TB.cpp

  ......

  - V e r i l a t i o n   R e p o r t: Verilator 5.043 ......
  - Verilator: Built from 0.063 MB sources in 3 modules, ......
  - Verilator: Walltime 3.316 s (elab=0.031,......

  make[1]: Leaving directory '.../simulation'

  TOP_MODULE=basic_loops make -C simulation run

  make[1]: Entering directory '.../simulation'

  ./obj_dir/Vbasic_loops

        SystemC 3.0.2-Accellera --- Dec  8 2025 10:15:05
        Copyright (c) 1996-2025 by all Contributors,
        ALL RIGHTS RESERVED

  Info: (I703) tracing timescale unit set: 100 ps
                               (sc_basic_loops_TB.vcd)

  Warning: (W509) module construction not properly completed:...

  Pass [  0]:RefOut=  389 | DutOut=  389
  Pass [  1]:RefOut=    5 | DutOut=    5
  Pass [  2]:RefOut=  170 | DutOut=  170
   ......
  Pass [ 98]:RefOut=   51 | DutOut=   51
  Pass [ 99]:RefOut=  -74 | DutOut=  -74
  Pass [100]:RefOut= -115 | DutOut= -115

5-3. 디지털 시뮬레이션 결과 파형

$ make wave

  TOP_MODULE=basic_loops make -C ./simulation wave

  make[1]: Entering directory '.../simulation'

  gtkwave Vbasic_loops.vcd --save=Vbasic_loops.gtkw &
  gtkwave sc_basic_loops_TB.vcd --save=sc_basic_loops_TB.gtkw &

핸드-쉐이크와 동기식 메모리 인터페이스 타이밍에 유의할 것

계산) 103-58+105+115+81-1+74-20+41-51=389

6. ETRI050 노드

"내 칩 제작 서비스" 0.5um Si-CMOS(2P3M) 공정

6-1. 합성 환경

$ pwd

    ~/ETRI050_DesignKit/Projects/HLS/basic_loops

$ make ETRI050

    Create ETRI050/log directory......
    Link ETRI050/source directory......
    Create ETRI050/synthesis directory......

    Vitis-HLS Project: basic_loops
      Targetting ETRI050 node,

      (1) Synthesize
        TOP_MODULE=basic_loops make synth_ETRI050
      (2) Netlist Simulation
        TOP_MODULE=basic_loops make sim_ETRI050
        TOP_MODULE=basic_loops make wave_ETRI050
      (3) P&R, Generate layout
        TOP_MODULE=basic_loops make pnr_ETRI050
      (4) View GDS
        TOP_MODULE=basic_loops make layout_ETRI050

$ cd ETRI050

$ ll

    total 48
    drwxr-xr-x 7 mychip mychip 4096 Dec  9 14:24 .
    drwxr-xr-x 8 mychip mychip 4096 Dec  9 11:08 ..
    drwxr-xr-x 2 mychip mychip 4096 Nov  5 17:45 chip_top
    drwxr-xr-x 2 mychip mychip 4096 Dec  9 14:25 layout
    drwxr-xr-x 2 mychip mychip 4096 Dec  9 14:27 log
    drwxr-xr-x 2 mychip mychip 4096 Dec  9 14:24 simulation
    lrwxrwxrwx 1 mychip mychip   42 Dec  9 14:24 source -> ../basic_loops/hls_component/syn/verilog
    drwxr-xr-x 2 mychip mychip 4096 Dec  9 14:27 synthesis
    -rw-r--r-- 1 mychip mychip 5118 Dec  9 14:24 Makefile
    -rw-r--r-- 1 mychip mychip 1771 Dec  9 14:27 project_vars.sh
    -rwxr--r-- 1 mychip mychip 1904 Dec  9 14:27 qflow_exec.sh
    -rw-r--r-- 1 mychip mychip  857 Dec  9 14:27 qflow_vars.sh

합성에서 레이아웃 GDS 를 만드는 칩 작업은 급격한 추상화 수준의 변화가 일어난다. 이 변화는 대부분 자동화 도구에 의한다. 그 과정에서 생성되는 각종 중간 파일들이 저장될 디렉토리들이 존재한다. HLS로 얻은 베릴로그 RTL이 저장된 디렉토리가 소스 ./source 로 심볼링크 되어있다.

6-2. RTL 합성

RTL 베릴로그로 기술된 basic_loops 모듈을 ETRI050 표준 셀의 네트리스트로 합성한다. 합성은 행위 묘사에서 논리회로로 변환하는 절차다.

$ make synthesize

    qflow synthesize -T etri050 basic_loops

합성기가 실시하는 주요 절차를 따라가 본다. 자세한 합성 기록은 ./log/synth.log 다.

    --------------------------------
    Qflow project setup
    --------------------------------

    Technology set to etri050
    Regenerating files for existing project basic_loops
    Technology .magicrc file has been updated.
    Technology .par file has been updated.

    Running yosys for verilog parsing and synthesis

목표 공정기술을 etri050으로 지정하고 라이브러리 정의 파일(리버티 형식, Liberty)을 읽어들인다.

    yosys  -s basic_loops.ys

    /--------------------------------------------------------------\
    |  yosys -- Yosys Open SYnthesis Suite                         |
    |  Copyright (C) 2012 - 2025  Claire Xenia Wolf                |
    |  Distributed under an ISC-like license, type "license"....   |
    \--------------------------------------------------------------/

    Yosys 0.60+8 (git sha1 0e31e389f, clang++ 18.1.3 -fPIC -O3)
    
-- Executing script file `basic_loops.ys' --

    1. Executing Liberty frontend:
         /usr/local/share/qflow/tech/etri050/etri05_stdcells.lib

    Imported 39 cell types from liberty file.

    2. Executing Verilog-2005 frontend: ./source/basic_loops.v
       Parsing Verilog input from `../basic_loops.v'
                             to AST representation.
        Generating RTLIL representation for module `\basic_loops'.

        Successfully finished Verilog frontend.

        ......

기본적인 문법 검사를 마치면 합성을 시작한다. 먼저 설계 계층 구조 구축,

    4. Executing SYNTH pass.

    4.1.2. Analyzing design hierarchy..
    Top module:  \basic_loops
    Used module:     \basic_loops_flow_control_loop_pipe
    Removed 0 unused modules.

절차구문(프로시져, 베릴로그의 always @(...)) 분석한다. 메모리, 레지스터 등 순차구문 요소들을 확인한다.

    4.2. Executing PROC pass (convert processes to netlists).

사용되지 않는 순차구문 제거, 초기화 속성(동기 또는 비동기 리셋과 프리셋) 확인,

    4.2.3. Executing PROC_PRUNE pass
            (remove redundant assignments in processes).
        ......
    4.2.4. Executing PROC_INIT pass (extract init attributes).
        Found init rule in
           `\basic_loops_flow_control_loop_pipe.
                $proc$basic_loops_flow_control_loop_pipe.v:51$93'.
        Set init value: \ap_loop_init = 1'1
        Found init rule in
           `\basic_loops.$proc$/source/basic_loops.v:73$88'.
          Set init value: \ap_CS_fsm = 1'1
          Set init value: \ap_enable_reg_pp0_iter1 = 1'0
          Set init value: \x1_fu_42 = 4'0000
          Set init value: \out_accum2_fu_46 = 12'000000000000
          Set init value: \ap_done_reg = 1'0

    4.2.5. Executing PROC_ARST pass
             (detect async resets in processes).

절차구문 내에 조합 구문(멀티 플렉서)여부 검사: 롬 구조 또는 멀티 플렉서(온전한 case ... 또는 if~else~문),

    4.2.6. Executing PROC_ROM pass (convert switches to ROMs).

    4.2.7. Executing PROC_MUX pass
                    (convert decision trees to multiplexers).

온전하지 않은 경우 래치,

    4.2.8. Executing PROC_DLATCH pass
            (convert process syncs to latches).

행위 묘사에서 합성한 디지털 논리식의 최적화 과정은 매우 길게 이어진다. 최적화된 논리식을 얻는 도구는 ABC(A System for Sequential Synthesis and Verification) 다.

    4.22.1.1. Executed ABC.
    Extracted 93 gates and 125 wires to a netlist network
             with 31 inputs and 26 outputs.
    Running ABC script: <abc-temp-dir>/abc.script
    ABC: UC Berkeley, ABC 1.01 (compiled Dec  9 2025 10:44:30)
    ......

    4.22.1.2. Re-integrating ABC results.
    ABC RESULTS:               AND cells:        6
    ABC RESULTS:            ANDNOT cells:       22
    ABC RESULTS:              NAND cells:        8
    ABC RESULTS:               NOR cells:        9
    ABC RESULTS:               NOT cells:        1
    ABC RESULTS:                OR cells:       13
    ABC RESULTS:             ORNOT cells:        3
    ABC RESULTS:              XNOR cells:       13
    ABC RESULTS:               XOR cells:       13
    ABC RESULTS:        internal signals:       68
    ABC RESULTS:           input signals:       31
    ABC RESULTS:          output signals:       26

        ......

합성과 최적화된 디지털 논리(식)에 사용된 표준 셀들의 통계를 보자.

    4.25. Printing statistics.

    === basic_loops ===
        +----------Local Count, excluding submodules.
        | 
      102 wires
      229 wire bits
       37 public wires
      164 public wire bits
       10 ports
       32 port bits
      107 cells
       22   $_ANDNOT_
        6   $_AND_
        4   $_DFFE_PP_
        1   $_DFF_P_
        8   $_NAND_
        9   $_NOR_
        1   $_NOT_
        3   $_ORNOT_
       13   $_OR_
       12   $_SDFFCE_PP0P_
        2   $_SDFF_PP0_
       13   $_XNOR_
       13   $_XOR_
        1 submodules
        1   basic_loops_flow_control_loop_pipe

=== basic_loops_flow_control_loop_pipe ===
        +----------Local Count, excluding submodules.
        | 
       14 wires
       14 wire bits
       13 public wires
       13 public wire bits
       13 ports
       13 port bits
        2 cells
        1   $_OR_
        1   $_SDFFE_PP1P_

논리 요소들 앞에 $는 내부의 가상 셀들로 표현되었다는 뜻이다. ETRI050 디자인 킷에서 제공하는 표준 셀로 변환 해야 한다. 만일 동일한 기능의 셀이 제공되지 않는다면 등가 논리식으로 변환한다. 이때에도 ABC 가 동원된다.

    7. Executing ABC pass (technology mapping using ABC).

    7.1. Extracting gate netlist of module `\basic_loops'
                     to `<abc-temp-dir>/input.blif'..

    7.1.1. Executed ABC.
    Extracted 118 gates and 150 wires to a netlist network
                                 with 31 inputs and 37 outputs.

    Running ABC script: <abc-temp-dir>/abc.script

    ABC: UC Berkeley, ABC 1.01 (compiled Dec  9 2025 10:44:30)
        ......

    ABC: Scl_LibertyReadGenlib() skipped sequential cell "DFFNEGX1".
    ABC: Scl_LibertyReadGenlib() skipped sequential cell "DFFPOSX1".
    ABC: Scl_LibertyReadGenlib() skipped sequential cell "DFFSR".
    ABC: Scl_LibertyReadGenlib() skipped cell "FAX1" due to dont_use attribute.
    ABC: Scl_LibertyReadGenlib() skipped cell "PADVDD" without logic function.
    ABC: Scl_LibertyReadGenlib() skipped cell "PADGND" without logic function.

    ABC: Library "etri05_stdcells" from
         "/usr/local/share/qflow/tech/etri050/etri05_stdcells.lib"
         has 24 cells (15 skipped: 4 seq; 1 tri-state; 4 no func;
                 6 dont_use; 0 with 2 outputs; 0 with 3+ outputs).

        ......

    7.1. Extracting gate netlist of module `\basic_loops'....

    7.1.2. Re-integrating ABC results.
    ABC RESULTS:            AND2X2 cells:       11
    ABC RESULTS:           AOI21X1 cells:        4
    ABC RESULTS:           AOI22X1 cells:        1
    ABC RESULTS:             INVX1 cells:       41
    ABC RESULTS:           NAND2X1 cells:       44
    ABC RESULTS:           NAND3X1 cells:       10
    ABC RESULTS:            NOR2X1 cells:       33
    ABC RESULTS:           OAI21X1 cells:       33
    ABC RESULTS:           OAI22X1 cells:        1
    ABC RESULTS:             OR2X2 cells:        7
    ABC RESULTS:        internal signals:       82
    ABC RESULTS:           input signals:       31
    ABC RESULTS:          output signals:       37

        ......

    7.2. Extracting gate netlist of module
                     `\basic_loops_flow_control_loop_pipe'......

    7.2.2. Re-integrating ABC results.
    ABC RESULTS:             INVX1 cells:        1
    ABC RESULTS:            NOR2X1 cells:        1
    ABC RESULTS:           OAI21X1 cells:        1
    ABC RESULTS:        internal signals:        4
    ABC RESULTS:           input signals:        4
    ABC RESULTS:          output signals:        1

        ......

    13. Printing statistics.

    === basic_loops ===
        +----------Local Count, excluding submodules.
        |
      190 wires
      241 wire bits
      190 public wires
      241 public wire bits
       10 ports
       32 port bits
      230 cells
        1   $scopeinfo
       11   AND2X2
        4   AOI21X1
        1   AOI22X1
       21   BUFX2
       20   DFFPOSX1
       42   INVX1
       44   NAND2X1
       10   NAND3X1
       34   NOR2X1
       34   OAI21X1
        1   OAI22X1
        7   OR2X2

    End of script. Logfile hash: ...
    Number of gates changed: 0

합성이 완료되어 네트리스트가 만들어 졌다. 이후 작업(자동 배치 배선과 LVS)를 위한 파일 형식 변환이 이뤄진다. 배치 후 배선을 하려면 표준 셀의 내부 풋 프린트(셀 크기와 포트위치, 배선 금지구역등)를 들여다 봐야 한다. 표준 셀과 배선 규칙들을 기록하는 형식은 LEF(Library Exchange Format)다.

    Running vlog2Verilog for antenna cell mapping.

    vlog2Verilog -c -p -v vdd -g gnd \
      -l /usr/local/share/qflow/tech/etri050/etri050_stdcells.lef \
      -o basic_loops.v basic_loops_sized.v

    Generating RTL verilog and SPICE netlist file in directory
    Files:
       Verilog: ./synthesis/basic_loops.rtl.v
       Verilog: ./synthesis/basic_loops.rtlnopwr.v
       Verilog: ./synthesis/basic_loops.rtlbb.v
       Spice:   ./synthesis/basic_loops.spc

향후 표준셀 배치배선을 마친 후 얻게될 레이아웃과 LVS(Layout-vs-Schematic)를 수행하기 위한 네트리스트를 만든다. 합성으로 얻은 네트리스트가 LVS 검사의 기준이 된다. 오픈-소스 LVS 도구는 netgen 이다. netgen은 SPICE 네트리스트 형식을 읽어 두 회로의 등가성을 검사한다.

    Running spi2xspice.py

    spi2xspice.py \
        "/usr/local/share/qflow/tech/etri050/etri05_stdcells.lib" \
        basic_loops.spc basic_loops.xspice

    Reading liberty netlist
        usr/local/share/qflow/tech/etri050/etri05_stdcells.lib

    Reading spice netlist basic_loops.spc

    Writing xspice netlist basic_loops.xspice

    Writing xspice file

    Done.

6-3. 합성 후 네트 시뮬레이션

....

$ cd simulation

$ make

    Netlist timing simulation using iVerilog-VPI:basic_loops

        TOP_MODULE=basic_loops HW_STYLE=HW_STYLE make build
        TOP_MODULE=basic_loops make run
        TOP_MODULE=basic_loops make wave

        TOP_MODULE=basic_loops make clean

$ ll

  total 1520
  drwxr-xr-x 2 ... .
  drwxr-xr-x 7 ... ..
  -rw-r--r-- 1 ... Makefile
  -rw-r--r-- 1 ... basic_loops_TB.v
  lrwxrwxrwx 1 ... sc_basic_loops_TB.cpp -> ../../simulation/sc_basic_loops_TB.cpp
  -rw-r--r-- 1 ... sc_basic_loops_TB.h
  -rw-r--r-- 1 ... vpi_basic_loops_tb.cpp
  -rw-r--r-- 1 ... vpi_basic_loops_tb_exports.h
  -rw-r--r-- 1 ... vpi_basic_loops_tb_ports.h
  -rw-r--r-- 1 ... vpi_stub.cpp

$ $ make build

    g++ -DVM_SC=1 \
        -I/usr/local/share/verilator/include \
        -I/usr/local/share/verilator/include/vltstd \
        -I/usr/local/include/iverilog -I/opt/systemc/include \
        -I../../c_untimed -I.. -L/opt/systemc/lib \
        -DHW_STYLE_SC -g -fPIC \
        ../../c_untimed/basic_loops.cpp \
        ./sc_basic_loops_TB.cpp \
        ./vpi_stub.cpp ./vpi_basic_loops_tb.cpp  \
        -o vpi_stub.vpi \
        -shared -latomic -lsystemc

    iverilog -g2005-sv -Tmin -gspecify -o basic_loops_TB  \
            basic_loops_TB.v  \
            ~/ETRI050_DesignKit/digital_ETRI/khu_etri05_stdcells.v  \
            ../synthesis/basic_loops_mapped.v

$ make run

    vvp -M. -mvpi_stub basic_loops_TB -v

    Icarus Verilog started
    VCD info: dumpfile basic_loops_TB.vcd opened for output.

    Info: (I703) tracing timescale unit set: 100 ps

    #0 s SystemC started
    Pass [  0]:RefOut=  389 | DutOut=  389
    Pass [  1]:RefOut=    5 | DutOut=    5
    Pass [  2]:RefOut=  170 | DutOut=  170
        ......
    Pass [ 98]:RefOut=   51 | DutOut=   51
    Pass [ 99]:RefOut=  -74 | DutOut=  -74
    Pass [100]:RefOut= -115 | DutOut= -115

    Info: /OSCI/SystemC: Simulation stopped by user

$ make wave

<그림 3,4>



6-4. 표준 셀 자동 배치와 배선

합성으로 얻은 네트리스트를 가지고 표준 셀 배치,

$ make place

    qflow place -T etri050 basic_loops

    --------------------------------
    Qflow project setup
    --------------------------------

    Technology set to etri050
    Regenerating files for existing project basic_loops
    Qrouter detail maze router version 1.4.88.T

    Reading LEF data from file
          /usr/local/share/qflow/tech/etri050/etri050_stdcells.lef.

    LEF file:  Defines site corner (ignored)
    LEF file:  Defines site IO (ignored)
    LEF file:  Defines site core (ignored)
    LEF read: Processed 3266 lines.

    LEF Read: encountered 0 errors and 8 warnings total.

베릴로그 네트리스트를 자동 배치 오픈-소스 도구 graywolf의 입력 파일 형식 .cel 로 변환,

    Running vlog2Cel to generate input files for graywolf

    vlog2Cel  -l \
         /usr/local/share/qflow/tech/etri050/etri050_stdcells.lef \
        -o ./layout/basic_loops.cel \
        ./synthesis/basic_loops.rtlnopwr.v

    Preparing pin placement hints from basic_loops.cel2

표준 셀 리버티와 입출력 핀 배치 파일 .cel2 참조하여 배치를 수행한다. 배치된 표준 셀의 빈 곳을 채우기 위해 필러 셀은 FILL 이다. 배치 후 배선도구가 사용할 네트리스트 형식은 DEF(Design Exchange Format)다.

    Running GrayWolf placement
    graywolf  basic_loops

    Running getantennacell to determine cell to use for antenna anchors.
    getantennacell.tcl basic_loops

    Running getfillcell to determine cell to use for fill.

    Running place2def to translate graywolf output to DEF format.
    place2def.tcl basic_loops FILL

    Running arrangepins to adjust pin positions for optimal routing.

    ......

<그림 5>

자동 배치로 얻은 DEF는 표준 셀 네트리스트에 표준 셀의 좌표와 놓인 방향 정보를 담고 있다.

$ ll layout

    total 348
    drwxr-xr-x 2 mychip mychip   4096 Dec  9 16:18 .
    drwxr-xr-x 7 mychip mychip   4096 Dec  9 14:24 ..
    -rw-r--r-- 1 mychip mychip    779 Dec  9 14:25 .magicrc
    -rw-r--r-- 1 mychip mychip  14563 Nov  5 17:45 ETRI050_CMOS.lyp
    -rw-r--r-- 1 mychip mychip   2862 Nov  5 17:45 Makefile
    -rw-r--r-- 1 mychip mychip 135246 Dec  9 16:18 basic_loops.cel
    -rw-r--r-- 1 mychip mychip     70 Dec  9 16:18 basic_loops.cel2
    -rw-r--r-- 1 mychip mychip    578 Dec  9 16:18 basic_loops.cfg
    -rw-r--r-- 1 mychip mychip  29126 Dec  9 16:18 basic_loops.def
    -rw-r--r-- 1 mychip mychip    116 Dec  9 16:18 basic_loops.info
    -rw-r--r-- 1 mychip mychip    320 Dec  9 16:18 basic_loops.obs
    -rw-r--r-- 1 mychip mychip   1671 Dec  9 14:25 basic_loops.par
    -rw-r--r-- 1 mychip mychip  69190 Dec  9 16:18 basic_loops.pin
    -rw-r--r-- 1 mychip mychip  11381 Dec  9 16:18 basic_loops.pl1
    -rw-r--r-- 1 mychip mychip   1807 Dec  9 16:18 basic_loops.pl2

$ less ./layout/basic_loops.def

    VERSION 5.6 ;
    DIVIDERCHAR "/" ;
    BUSBITCHARS "[]" ;
    DESIGN basic_loops ;
    UNITS DISTANCE MICRONS 100 ;

    DIEAREA ( -600 -600 ) ( 35700 36900 ) ;

    TRACKS Y -600 DO 126 STEP 300 LAYER metal1 ;
    TRACKS X -600 DO 122 STEP 300 LAYER metal2 ;
    TRACKS Y -600 DO 126 STEP 300 LAYER metal3 ;

    COMPONENTS 249 ;
    - _386_ BUFX2 + PLACED ( 150 150 ) S ;
    - _384_ BUFX2 + PLACED ( 1350 150 ) S ;
    - _316_ OR2X2 + PLACED ( 2550 150 ) S ;
    - _318_ NAND3X1 + PLACED ( 4050 150 ) FS ;
    - _319_ OAI21X1 + PLACED ( 5550 150 ) S ;
        ......
    - _208_ OR2X2 + PLACED ( 22650 10950 ) N ;
    - CLKBUF1_insert0 CLKBUF1 + PLACED ( 24150 10950 ) N ;
    - _363_ DFFPOSX1 + PLACED ( 27150 10950 ) N ;

        ......
    - FILL34650x18150 FILL + PLACED ( 34650 18150 ) N ;
    - FILL34650x25350 FILL + PLACED ( 34650 25350 ) N ;
    - FILL34650x28950 FILL + PLACED ( 34650 28950 ) S ;
    END COMPONENTS

    PINS 34 ;
    - gnd + NET gnd
      + LAYER metal1 ( -450 0 ) ( 450 0 )
      + PLACED ( 35580 30 ) N ;
    - vdd + NET vdd
      + LAYER metal1 ( -450 0 ) ( 450 0 )
      + PLACED ( -480 30 ) N ;
    - ap_clk + NET ap_clk
      + LAYER metal2 ( -52 -52 ) ( 52 52 )
      + PLACED ( 21300 36900 ) N ;
        ......
    END PINS

    NETS 245 ;
    - ap_clk
      ( PIN ap_clk ) 
      ( CLKBUF1_insert0 A ) 
      ( CLKBUF1_insert1 A ) 
      ( CLKBUF1_insert2 A ) 
      ( CLKBUF1_insert3 A ) ;
    - ap_clk_bF$buf0
      ( _365_ CLK ) 
      ( _359_ CLK ) 
      ( _370_ CLK ) 
      ( _376_ CLK ) 
      ( _361_ CLK ) 
      ( CLKBUF1_insert3 Y ) ;

배치하는 중에 구동력이 부족한 경우 버퍼가 삽입되기도 한다. 표준 셀 배선 도구는 qrouter 다. 자동 배치로 얻은 DEF를 읽어 배선 규칙에 따라 자동 배선 한다. 자동 배선 규칙이 포함된 배선 명령 스크립트 파일은 basic_loops.cfg 다.

$ cat ./layout/basic_loops.cfg

    # qrouter runtime script for project basic_loops
    verbose 1
    read_lef 
        /usr/local/share/qflow/tech/etri050/etri050_stdcells.lef

    catch {layers 3}

    via stack none

    vdd vdd
    gnd gnd

    obstruction -9.0 364.5 360.0 372.0 metal1
    obstruction -9.0 -9.0 360.0 1.5 metal1
        ......
    obstruction 1.5 364.5 352.5 372.0 metal3
    obstruction 1.5 -9.0 352.5 1.5 metal3
    obstruction -9.0 1.5 1.5 364.5 metal2
    obstruction 352.5 1.5 360.0 364.5 metal2

    read_def basic_loops.def

    qrouter::standard_route basic_loops_route.def false

    quit

적층 비아를 금지하고 이미 표준셀이 점유 중인 배선할 수 없는 영역(obstruction)을 지정하고 있다.

$ make route

    qflow route -T etri050 basic_loops

    Running qrouter 1.4.88.T
    qrouter -noc  -s basic_loops.cfg

    *** Running stage1 routing with defaults
    Nets remaining: 200
    Nets remaining: 100
        ......

    Progress: Stage 1 total routes completed: 463
    Failed net routes: 9

    *** Running stage2 routing with options mask 10, effort 10
    Nets remaining: 9
    Nets remaining: 9
        ......

    Nets remaining: 1

    Progress: Stage 2 total routes completed: 508
    No failed routes!

    *** Running stage3 routing with defaults, 1st round
    Nets remaining: 200
    Nets remaining: 100
    Nets remaining: 80
        ......

    Nets remaining: 4
    Nets remaining: 1

    Progress: Stage 3 total routes completed: 929
    No failed routes!

    *** Running stage3 routing with defaults, 2nd round
    Nets remaining: 200
        ......
    Nets remaining: 1

    Progress: Stage 3 total routes completed: 1344
    No failed routes!

    *** Writing DEF file basic_loops_route.def

    Final: No failed routes!

최적의 배선을 위해 몇회 반복한다. 배선까지 마친 DEF에서 RC 정보를 추출하고 배선 전과 후를 비교하기 위해 네트리스트를 추출한다. 표준 셀을 배치하는 과정에서 구동력이 부족한 경우 버퍼 셀이 삽입되기도 하므로 배선까지 마친 네트리스트를 다시 추출한다.

    *** Writing RC file basic_loops_route.rc

    DEF2Verilog -v ./synthesis/basic_loops.rtlnopwr.v \
            -o ./synthesis/basic_loops_postroute.v \
            /usr/local/share/qflow/tech/etri050/etri050_stdcells.lef
            basic_loops_route.def

    Generating RTL verilog and SPICE netlist file in directory
    Running vlog2Verilog.
    vlog2Verilog -c -v vdd -g gnd \
            -o basic_loops.rtl.anno.v basic_loops_postroute.v

    Running vlog2Spice.
    vlog2Spice -i \
    -l  /usr/local/share/qflow/tech/etri050/etri050_stdcells.sp \
    -o basic_loops.anno.spc basic_loops.rtl.anno.v

배선을 마친 DEF(./layer/basic_loops.def)에는 네트에 배선의 좌표와 필러셀 들이 포함된다.

    COMPONENTS 249 ;
    - _386_ BUFX2 + PLACED ( 150 150 ) S ;
    - _384_ BUFX2 + PLACED ( 1350 150 ) S ;
    - _316_ OR2X2 + PLACED ( 2550 150 ) S ;

        ......

    - FILL34650x18150 FILL + PLACED ( 34650 18150 ) N ;
    - FILL34650x25350 FILL + PLACED ( 34650 25350 ) N ;
    - FILL34650x28950 FILL + PLACED ( 34650 28950 ) S ;

    END COMPONENTS

    PINS 34 ;
    - gnd + NET gnd
      + LAYER metal1 ( -450 0 ) ( 450 0 )
      + PLACED ( 35580 30 ) N ;
    - vdd + NET vdd
      + LAYER metal1 ( -450 0 ) ( 450 0 )
      + PLACED ( -480 30 ) N ;
    - ap_clk + NET ap_clk
      + LAYER metal2 ( -52 -52 ) ( 52 52 )
      + PLACED ( 21300 36900 ) N ;
        ......
    - ap_return[0] + NET ap_return[0]
      + LAYER metal3 ( -60 -60 ) ( 60 60 )
      + PLACED ( 35700 19500 ) N ;
    END PINS

    NETS 245 ;
    - ap_clk
      ( PIN ap_clk ) 
      ( CLKBUF1_insert0 A ) 
      ( CLKBUF1_insert1 A ) 
      ( CLKBUF1_insert2 A ) 
      ( CLKBUF1_insert3 A ) 
    + ROUTED metal2 ( 9300 16500 ) ( * 16200 ) M3_M2 
      NEW metal3 ( 9300 16200 ) ( 17700 * ) M3_M2 
      NEW metal2 ( 17700 16200 ) ( * 16500 ) 
      NEW metal2 ( 24600 12600 ) ( * 13500 ) M3_M2 
      NEW metal3 ( 24600 13500 ) ( 17700 * ) M3_M2 
        ......
    + ROUTED metal2 (27900 36900) (28200 *) (* 33900) (27900 *) ;
    - ap_return[9]
      ( PIN ap_return[9] ) 
      ( _402_ Y ) 
    + ROUTED metal2 (18300 36900) (18000 *) (* 33900) (18300 *) ;
    END NETS

6-5. 표준 셀 병합과 LVS 검사

배치와 배선을 완료한 DEF에 표준 셀의 내부 트랜지스터 회로(레이아웃)을 병합한다.

$ make migrate

    qflow migrate -T etri050 basic_loops

    --------------------------------
    Qflow project setup
    --------------------------------

    Technology set to etri050
    Regenerating files for existing project basic_loops
    Running magic 8.3.538
    magic -dnull -noconsole  migrate_basic_loops.tcl

    Magic 8.3 revision 538

    Starting magic under Tcl interpreter
    Using the terminal as the console.

        ......

    Loading "migrate_basic_loops.tcl" from command line.

    Root cell box:
           width x height  (   llx,  lly  ), (   urx,  ury  )
    microns:   0.000 x 0.000   ( 0.000,  0.000), ( 0.000,  0.000)
    lambda:     0.00 x 0.00    (  0.00,  0.00 ), (  0.00,  0.00 )
    internal:      0 x 0       (     0,  0    ), (     0,  0    )

    Reading LEF data from file
        /usr/local/share/qflow/tech/etri050/etri050_stdcells.lef.

    This action cannot be undone.
    LEF read: Processed 3266 lines.
    Reading DEF data from file basic_loops.def.

    This action cannot be undone.
    DEF read, Line 13 (Error): END statement out of context.
      Processed 249 subcell instances total.
      Processed 34 pins total.
      Processed 245 nets total.
      Processed 2 special nets total.

    Generating LEF output basic_loops.lef for cell basic_loops:
    Diagnostic:  Write LEF header for cell basic_loops
    Diagnostic:  Writing LEF output for cell basic_loops

    Diagnostic:  Scale value is 0.150000
    Extracting BUFX2 into BUFX2.ext:
    Extracting OR2X2 into OR2X2.ext:
    Extracting NOR2X1 into NOR2X1.ext:
    Extracting OAI21X1 into OAI21X1.ext:
    Extracting NAND3X1 into NAND3X1.ext:
        ......
    Extracting CLKBUF1 into CLKBUF1.ext:
    Extracting OAI22X1 into OAI22X1.ext:
    Extracting AOI21X1 into AOI21X1.ext:
    Extracting basic_loops into basic_loops.ext:

    exttospice finished.

표준 셀이 병합된 레이아웃에서 LVS 에서 사용될  추출된 SPICE 네트리스트가 추출 된다. 병합된 레이아웃에서 트랜지스터의 네트리스트를 역추출한 후 LVS 검사를 수행할 수 있다. 오픈-소스 LVS 도구는 netgen 이다. 합성으로 얻은 네트리스트와 배치배선이 완료된 레이아웃에서 추출된 네트리스트를 비교하여 등가성을 검사한다.

$ make lvs

    ~/ETRI050_DesignKit/scripts/fix_net_name.sh \
                        ./synthesis/basic_loops.spc

    ***************************************************
    * Replace back-slash with underscore on netname
    ***************************************************

    qflow lvs -T etri050 basic_loops

    --------------------------------
    Qflow project setup
    --------------------------------

    Technology set to etri050
    Regenerating files for existing project basic_loops

    Running netgen

    netgen -batch lvs "basic_loops.spice basic_loops"  \
            "./synthesis/basic_loops.spc basic_loops"  \
            /usr/local/share/qflow/tech/etri050/etri050_setup.tcl  \
            comp.out -json -blackbox

    Netgen 1.5.295 compiled on Sat Aug  9 00:37:50 KST 2025

      ......

    Contents of circuit 1:  Circuit: 'basic_loops'
    Circuit basic_loops contains 233 device instances.
        ......
      Class: NOR2X1                instances:  34
      Class: NAND3X1               instances:  10
      Class: OAI22X1               instances:   1
      Class: DFFPOSX1              instances:  20
        ......
      Class: INVX1                 instances:  39
      Class: INVX2                 instances:   3
    Circuit contains 246 nets.

    Contents of circuit 2:  Circuit: 'basic_loops'
    Circuit basic_loops contains 233 device instances.

        ......
      Class: NOR2X1                instances:  34
      Class: NAND3X1               instances:  10
      Class: OAI22X1               instances:   1
      Class: DFFPOSX1              instances:  20
        ......
      Class: INVX1                 instances:  39
      Class: INVX2                 instances:   3
    Circuit contains 246 nets.

    Circuit 1 contains 233 devices, Circuit 2 contains 233 devices.
    Circuit 1 contains 246 nets,    Circuit 2 contains 246 nets.

    Final result:
        Circuits match uniquely.

    Logging to file "comp.out" disabled

    LVS Done.

    Running count_lvs.py

    /usr/local/share/qflow/scripts/count_lvs.py
    LVS reports no net, device, pin, or property mismatches.

    Total errors = 0

LVS 검사항목은 배선(net)을 포함하여 입출력 핀(pin) 그리고 트랜지스터의 갯수(device)와 특성(폭과 길이, property)들을 포함된다.

6-6. 레이아웃의 크기 측정

"내칩 제작 서비스" MPW의 표준 칩의 크기는 1900x1900um 다. 표준 입출력 패드를 고려하면 사용 가능한 설계영역(코어 크기)는 1000x1000 이내로 제한 된다.

$ make size

    ~/ETRI050_DesignKit/scripts/size_core.sh basic_loops

    **************************************************************
    * Measure the size of the Core
    **************************************************************

    Magic 8.3 revision 538
    Starting magic under Tcl interpreter
    Using the terminal as the console.

    Processing system .magicrc file
    Using technology "scmos", version 2001a

        ......

    Root cell box:
           width x height  (   llx,  lly  ), (   urx,  ury  )  area (units^2)
    microns:  369.600 x 373.050  (-9.300, -3.600), ( 360.300,  369.450)  137879.297
    lambda:   1232.00 x 1243.50  (-31.00, -12.00), ( 1201.00,  1231.50)  1531992.00
    internal:   2464 x 2487    (   -62, -24   ), (  2402,  2463 )  6127968

7. 레이아웃 검사

자동화 도구에 의하여 생성된 레이아웃을 "내칩 제작 서비스"의 공정에서 요구하는 규정에 부합하는지 최종 검사한다. 자동배치와 배선을 마친 Magic 레이아웃이 저장되는 디렉토리는 ./layout 이다.

$ cd layout

$ pwd

    ~/ETRI050_DesignKit/Projects/HLS/basic_loops/ETRI050/layout

표준 셀들이 병합된 레이아웃은 오픈-소스 레이아웃 도구 Magic 의 형식으로 파일 확장명은 .mag 다.

$ ll

    total 988
    drwxr-xr-x 2 mychip mychip   4096 Dec 10 12:00 .
    drwxr-xr-x 7 mychip mychip   4096 Dec  9 14:24 ..
    -rw-r--r-- 1 mychip mychip    779 Dec  9 14:25 .magicrc
    -rw-r--r-- 1 mychip mychip    779 Dec  9 14:25 .magicrc.orig
    -rw-r--r-- 1 mychip mychip  14563 Nov  5 17:45 ETRI050_CMOS.lyp
    -rw-r--r-- 1 mychip mychip   2862 Nov  5 17:45 Makefile
    -rw-r--r-- 1 mychip mychip 135246 Dec  9 16:33 basic_loops.cel
    -rw-r--r-- 1 mychip mychip     70 Dec  9 16:18 basic_loops.cel2
    -rw-r--r-- 1 mychip mychip    578 Dec  9 16:33 basic_loops.cfg
    -rw-r--r-- 1 mychip mychip  84185 Dec  9 16:44 basic_loops.def
    -rw-r--r-- 1 mychip mychip 453348 Dec 10 11:53 basic_loops.lef
    -rw-r--r-- 1 mychip mychip  73697 Dec 10 11:53 basic_loops.mag
    
-rw-r--r-- 1 mychip mychip   1671 Dec  9 14:25 basic_loops.par
        ......
    -rw-r--r-- 1 mychip mychip  22924 Dec  9 16:44 basic_loops.rc
    -rw-r--r-- 1 mychip mychip  13126 Dec 10 11:53 basic_loops.spice
        ......

7-1. 적층 비아 검사(Stacked VIA)


7-2. 디자인 룰 검사 (Design Rule Check)


7-3. 네트리스트 등가 검사(Layout-Vs-Schematic)


8. 칩 탑(Chip Top)

입출력 패드 부착 후 공정에 제출할 최종 레이아웃 생성

MPW의 표준 패드 프레임 복사

코어 복사

표준 패드 프레임에 코어 레이아웃 넣기

입출력 패드 배치

코어와 입출력 패드 배선