TikZ 하드웨어 그림 (hwfig v1.1)은(는) 무엇을 하나요?
사용자가 LaTeX/TikZ로 하드웨어 그림(예: HLS/FPGA 커널의 데이터플로우, 양자화된 NN 계층, Versal/Zynq SoC 블록 다이어그램, AI Engine 어레이, 시스톨릭 어레이, 가산기 트리, 파이프라인, NoC, 메모리 계층, 클록 도메인, 플로어플랜)을 원할 때 이 스킬을 사용하십시오. 출력은 항상 편집 가능한 TikZ 소스와 함께 컴파일된 PDF/PNG 미리보기입니다.
작업 흐름
- 패키지 가져오기.
hwfig.sty를 이 스킬의 기본 디렉토리에서 작업 디렉토리로 복사합니다(사용자가 이미 복사본을 가지고 있지 않은 한 — 사용자 복사본의\ProvidesPackage줄에v1.1이 없으면 업데이트를 제안하세요). 파일을 읽고 바이트 단위로 복사하십시오. 절대 다시 입력하거나 인라인으로 스타일을 재정의하지 마십시오. 팔레트는 역할 색상을 통해서만 작동합니다. - 팔레트 선택 (기본값
grey), 패키지 옵션\usepackage[okabe]{hwfig}또는\hwpalette{...}(그룹-로컬, 그림마다 적용):grey— 인쇄/저널 기본값, 참조 템플릿을 따름(흰색 계산 상자, 회색 양자화기, 점선 회색 상수).okabe— Okabe–Ito, 색맹 안전, 가장 강한 대비. 컬러 논문에 좋은 기본값.tol— Paul Tol muted, 색맹 안전, 부드러움.nord— 차가운 톤, 슬라이드용.slate— 청회색 + 자주색 + 산호색, 과학 슬라이드 데크에 적합. 사용자가 지정하지 않으면grey로 생성하고 하나의 컬러 팔레트를 제안하십시오. 비교를 위해 여러 팔레트로 같은 그림을 컴파일하려면 (standalone문서 내부에서\foreach \pal in {grey,okabe,...}{\hwpalette{\pal}...}루프를 사용하면 각 페이지가 한 팔레트가 됩니다). 알 수 없는 팔레트 이름은 하드 오류입니다.
- 먼저 격자에 레이아웃을 스케치 (명시적
at (x,y)좌표, 약 2.4 cm 열 간격, ±1.4 cm 행), 그런 다음 배선. 밀집된 데이터플로우 그림에서는 명시적 좌표가positioning라이브러리보다 좋습니다. - 컴파일은
\documentclass[tikz,border=4pt]{standalone}+\usepackage{hwfig}로pdflatex -interaction=batchmode -halt-on-error(타임아웃 설정;nonstopmode는 중단될 수 있음) 사용,pdftoppm -r 110 -png로 래스터화하고, PNG를 보고 겹침(와이어 위의 레이블, 상자를 가로지르는 와이어, 충돌하는 제목, 노드에 닿는 프레임 레이블 등)을 수정한 후 전달하십시오. 깔끔해질 때까지 반복하십시오. - 전달은
.tex(논문에 바로 붙여넣을 수 있는 그림 본문),.sty, PDF를 함께 제공합니다. 사용자에게 논문에서\usepackage{hwfig}(또는\usepackage[<palette>]{hwfig})가 필요함을 상기시키십시오.
시각적 문법 (일관성 유지)
- 데이터는 왼쪽 → 오른쪽으로 흐릅니다. 기본 경로는 수평 축에 있고, 평행 분기는 위/아래 (±1.4 cm)에 있습니다.
- 컴파일 타임 상수 (
ctime, 점선 상자)는 설정하는 블록 바로 위/아래에 있으며darr(점선 화살표)로 연결됩니다. - 정밀도를 변경하는 모든 계산 블록 뒤에는
qbox(재양자화/시프트/포화)가 옵니다. - 분기는 수직으로 접근하는 엘보우 와이어로
op노드에 합류합니다:\draw[arr] (qr.east) -| ($(sum.north)+(0,0.32)$) -- (sum.north); - 하나의 소스에서 대체 분기: 점이 있는 포크 좌표,
\fill[hwwire] (fork) circle (1.3pt);, 그 다음 각 분기로|-엘보우. - 임계/강조 경로에는
hot을, 넓은 데이터 경로에는pic[pos=.5]{buswidth=512}와 함께bus를, 프로토콜 이름에는node[lbl,midway,above]{AXI4-S}(lblbox는 레이블이 교차하는 와이어 위에 있어야 할 때)를 사용하십시오. - 그룹화 프레임은 배경 레이어에
fit으로 추가합니다:\begin{scope}[on background layer]\node[group,fit=(a)(b),label={[grouplabel]above:PL}] {};\end{scope} - 클록 도메인:
clkdomain(강조 색상, 점선) 또는clkdomain=<color>; 교차점을cdc노드로 표시. - 모든 그림은
\begin{tikzpicture}[hw]로 시작 (글꼴\footnotesize, 선 두께, 화살표 끝 모양 설정).
라우팅 및 레이블 (모든 PNG에서 확인)
- 영역 간 여백. 인접한 프레임(Runtime | Message passing, PL | AIE) 사이에 최소 0.6 cm 이상의 간격을 두십시오. 노드, 합류
op, 와이어는 절대 프레임 가장자리 위에 놓이면 안 됩니다. 노드가 어느 프레임에도 속하지 않으면, 두 프레임 외부에 공간을 주십시오. - 라우팅 채널. 영역 사이의 와이어는 프레임 사이의 빈 채널(정의:
\def\chan{6.7})을 통해 달리고, 그런 다음 대상 프레임 아래/위의 자체 수평 레벨 (\def\lvla{-1.7})로 이동합니다. 두 와이어가 레벨을 공유하지 않도록 하고, 와이어와 평행한 프레임 가장자리 또는 블록 측면 사이에 최소 0.3 cm, 평행 와이어 사이에 최소 0.4 cm의 간격을 유지하십시오. - 레이블은 빈 세그먼트에만 배치.
lbl/buswidth는 완전히 빈 공간에 있는 세그먼트에만 배치하십시오(와이어가 프레임 경계를 교차하는 곳이나 블록에서 약 0.2 cm 이내에는 절대 배치 금지). 유일한 빈 구간이 수직이면 레이블을 아래에서 위로 읽을 수 있도록 회전:node[lbl,rotate=90,below]{AXI4-S}. 짧은 링크에서는pic[pos=.35..0.4]를 사용하여 숫자가 대상 블록에서 벗어나도록 하십시오. - 레이블이 있는 엘보우의 명시적 세그먼트.
-|/|-는 선택한 구간에 레이블을 취할 수 없습니다. 모서리를 직접 작성:(a.east) -- (\chan,ya) -- node[lbl,...]{X} (\chan,\lvla) -- (b.south|-{(0,\lvla)}) -- (b.south); - 레이블의 수학:
$W_{\mathrm{root}}$; 두 줄 레이블은\\사용 (모든 스타일은align=center설정).
노드 스타일 (모든 팔레트 인식)
| 스타일 | 용도 |
|---|---|
runtime | 실행 시간 입력/출력, 포트, 텐서 |
ctime | 컴파일 타임 상수: 가중치, 스케일, 설정 |
hlsbox | 계산 커널 / HLS 함수 / AIE 커널 |
qbox | 양자화기, 재양자화, 시프트+포화 |
op | +, ×, max (원) |
mux, demux | 멀티플렉서(입력 서쪽, 출력 동쪽) / 디멀티플렉서(미러) |
mem, bram, uram | 온칩 버퍼 |
fifo | 스트림/FIFO |
reg / ff | 클록 웨지가 있는 레지스터 |
lut, dsp | FPGA 기본 요소 (dsp는 오른쪽 상단 모서리 바깥에 작은 "DSP" 태그를 넣습니다 — 공간 확보) |
extmem | DDR / HBM (원통형) |
cpu | PS / ARM / RISC-V (이중 프레임) |
host | 호스트 CPU (PCIe 측) |
xbar | AXI 상호 연결 / NoC 막대 (\rotatebox{90}{AXI IC}) |
router | NoC 라우터/스위치 (다이아몬드) |
pe | 처리 요소 |
aie | AI Engine 타일 (코어 + 로컬 메모리; 코어 중앙에 레이블) |
chip | 패키지/다이 (핀 포함) |
port | 작은 핀 마커 |
cdc | 클록 도메인 교차 동기화기 |
group, plregion, psregion, clkdomain | 배경 프레임 |
grouplabel, lbl, lblbox | 프레임 제목, 와이어 레이블 (lblbox = 흰색 배경) |
엣지 스타일: arr, darr, bus, hot. 버스 틱: pic[pos=.5]{buswidth=32} (숫자는 틱 오른쪽) 또는 buswidth'=32 (왼쪽).
매개변수형 픽스
pic당 옵션 전달 — 해당 pic에만 로컬로 적용되므로, 다양한 크기가 하나의 그림을 공유할 수 있습니다:
\pic (A) at (0,0) {aiearray={rows=2,cols=4}};. \hwset{key=value,...}는 현재 범위의 나머지에 대한 기본값을 설정합니다. 내부 노드는 (name-...)로 주소 지정 가능합니다.
| pic | 키 | 주소 지정 가능한 부분 |
|---|---|---|
aiearray | rows, cols, dx, dy, tilelabel | 타일 (n-t<r>-<c>) (r=1 하단), 쉼 (n-s<c>), 프레임 (n-box) |
systolic | rows, cols | (n-pe<r>-<c>) (r=1 상단) |
addertree | depth (2^depth 입력) | 입력 (n-in<k>), 가산기 (n-a<level>-<k>), 출력 (n-out) |
pipeline | labels={Load,MAC,Requant,...} | 단계 (n-st<k>), 레지스터 (n-r<k>) |
noc | rows, cols, nocpe (true/false) | 라우터 (n-n<r>-<c>), PE (n-pe<r>-<c>) |
fabric | columns={I,C,C,D,C,B,...}, fabricrows (모든 값) | 열 상단 (n-c<k>). C=CLB D=DSP B=BRAM U=URAM I=IO |
legend | legend={comp/Compute,mem/BRAM,...} (roles: io comp quant const op mem ctrl group); 자동 간격 | — |
와이어는 pic 주위로 라우팅 (예: 아래에서 쉼 타일로: (k1.east) -- ++(0.9,0) |- ($(arr-s1.south)+(0,-0.35)$) -- (arr-s1.south)), 절대 타일을 통과하지 않도록.
사용자 정의 팔레트
@ 내부 메커니즘 불필요 — 8가지 역할(그리기, 채우기)과 세 가지 와이어 색상을 모두 설정:
\hwdefinepalette{mine}{%
\hwrole{io}{black}{white} \hwrole{comp}{teal}{teal!12} \hwrole{quant}{orange}{orange!15}
\hwrole{const}{black!55}{black!4} \hwrole{op}{red!70!black}{red!10} \hwrole{mem}{blue!60!black}{blue!10}
\hwrole{ctrl}{violet}{violet!10} \hwrole{group}{teal!40}{teal!3}
\hwwires{black}{black!50}{red!70!black}} % 와이어, 상수 와이어, 강조/핫
\hwpalette{mine}
채우기는 25% 이하의 농도로 유지하여 검은 텍스트를 읽을 수 있게 하고, 회색조 변환에서도 역할이 분리되는지 확인하십시오.
주의 사항
.tex파일은 파일 쓰기 도구로 작성하고, 셸 히어독,sed또는 Python 문자열 리터럴로 작성하지 마십시오: 이런 도구들은\\를\로 (또는\c...를 제어 문자로) 바꾸거나 노드 텍스트의 줄 바꿈을 깨뜨리는 경우가 많습니다.label=텍스트 내부의 콜론이나 쉼표는 키-값 구문 분석을 깨뜨립니다 — 중괄호로 감싸십시오:label={[grouplabel]above:{INT8: shifts}}.fit=목록은($(a)+(1,2)$)를 포함할 수 없습니다 (쉼표가 목록을 분할함); 먼저 명명된\coordinate를 정의하십시오.- 노드 내부에 추가 줄을 넣으려면
align=center와\\[-2pt]{\tiny ...}가 있는 일반 노드를 사용하십시오 — 상자에 두 번째 레이블을 겹쳐 놓지 마십시오. shapes.geometrictrapezium을 빈 텍스트와 함께 사용하면 0으로 나누기 오류가 발생합니다 — 이것이mux/demux가 사용자 정의 경로 그림인 이유입니다; 다시 바꾸지 마십시오.\foreach내부에서 노드 이름에 값을 사용하기 전에 정수 산술을 위해\pgfmathtruncatemacro를 사용하십시오;\foreach \a/\b in {...}에서 레이블 텍스트 내부의/는 분할을 일으킵니다 (I/O대신Port로 작성).clkdomain은 밝은 채우기가 있습니다;fabric이나 다른 밀집된 내용 위에 그릴 때는fill=none을 전달하십시오.- MiKTeX는 POSIX 스타일
TEXINPUTS를 무시합니다;hwfig.sty를.tex옆에 두십시오 (또는--include-directory=<windows path>전달). - 그림은 두 칼럼 논문에서
\footnotesize일 때 폭이 약 16 cm를 넘지 않도록 유지하십시오; 최후의 수단으로만\resizebox{\linewidth}{!}{...}로 크기 조정하십시오.
참조 예제 (GNN 계층, 하우스 템플릿)
\begin{tikzpicture}[hw]
\node[runtime] (xin) at (-0.9,1.4) {$X_i$};
\node[runtime] (xein) at (-0.9,-1.4) {$(X,E)$};
\node[hlsbox] (root) at (2.5,1.4) {Root\\$W_{\mathrm{root}}x_i$};
\node[qbox] (qr) at (4.9,1.4) {$Q_r$\\shift + sat8};
\node[mem] (agg) at (2.5,-1.4) {Mean aggregation\\$m_i$};
\node[hlsbox] (neigh) at (5.5,-1.4) {Neighbor\\$W_{\mathrm{neigh}}m_i+b$};
\node[qbox] (qn) at (8.1,-1.4) {$Q_n$\\shift + sat8};
\node[op] (sum) at (9.8,0) {$+$};
\node[qbox,minimum width=1.45cm] (qc) at (11.6,0) {sat8};
\node[hlsbox,minimum width=1.55cm] (relu) at (13.6,0) {$\rho_l$\\ReLU / id.};
\node[runtime] (yout) at (15.5,0) {$y_i^{(l)}$};
\node[ctime] (wroot) at (2.5,2.45) {$W_{\mathrm{root}}$};
\node[ctime] (wneigh) at (5.5,-2.55) {$W_{\mathrm{neigh}},b$};
\node[ctime] (sr) at (4.9,2.45) {$S_r$};
\node[ctime] (sn) at (8.1,-2.55) {$S_n$};
\node[ctrl] (fsm) at (13.6,-1.6) {Layer FSM};
\draw[arr] (xin)--(root);
\draw[bus] (xein)--(agg) pic[pos=.5]{buswidth=16};
\draw[arr] (agg)--(neigh);
\draw[arr] (root)--(qr);
\draw[arr] (neigh)--(qn);
\draw[arr] (qr.east) -| ($(sum.north)+(0,0.32)$) -- (sum.north);
\draw[arr] (qn.east) -| ($(sum.south)+(0,-0.32)$) -- (sum.south);
\draw[hot] (sum)--(qc);
\draw[hot] (qc)--(relu);
\draw[hot] (relu)--(yout);
\draw[darr] (wroot)--(root);
\draw[darr] (wneigh)--(neigh);
\draw[darr] (sr)--(qr);
\draw[darr] (sn)--(qn);
\draw[darr] (fsm)--(relu);
\begin{scope}[on background layer]
\node[group,fit=(xin)(xein),label={[grouplabel]above:Runtime}] {};
\node[group,fit=(root)(qr)(agg)(neigh)(qn)(wroot)(wneigh),label={[grouplabel]above:Message passing}] {};
\end{scope}
\end{tikzpicture}
참조 예제 (Versal SoC)
\begin{tikzpicture}[hw]
\node[host] (host) at (-3.4,0.3) {Host\\(x86)};
\node[cpu] (ps) at (0,2.2) {PS\\Cortex-A72};
\node[extmem] (ddr) at (0,-2.0) {DDR4};
\node[xbar,minimum height=5.6cm] (noc) at (2,0.1) {\rotatebox{90}{NoC}};
\node[hlsbox] (k1) at (4.7,1.6) {mm2s\\(HLS)};
\node[hlsbox] (k2) at (4.7,-2.3) {s2mm\\(HLS)};
\node[bram] (buf) at (4.7,-0.35) {BRAM buf};
\pic (arr) at (8.3,0.1) {aiearray};
% 라우팅 레벨
\def\chan{6.7} % PL과 AIE 영역 사이의 수직 채널
\def\lvla{-1.7} % mm2s -> AIE, AIE 프레임 아래
\def\lvlb{-2.3} % AIE -> s2mm, 한 레벨 아래 (= s2mm 행)
\draw[bus] (host) -- (host-|noc.west) node[lbl,midway,above=2pt]{PCIe Gen4};
\draw[arr] (ps.east) -- (ps-|noc.west);
\draw[arr,<->] (ddr.east) -- (ddr-|noc.west);
\draw[bus] (k1-|noc.east) -- (k1) pic[pos=.4]{buswidth=128};
\draw[bus] (k2) -- (k2-|noc.east);
% mm2s -> 쉼 1: 오른쪽으로 채널 진입, 아래로, 레벨 a 따라, 위로 쉼으로
\draw[arr] (k1.east) -- (\chan,1.6)
-- node[lbl,rotate=90,below]{AXI4-S} (\chan,\lvla)
-- (arr-s1.south|-{(0,\lvla)}) -- (arr-s1.south);
% 쉼 4 -> s2mm: 아래로 레벨 b까지, 왼쪽으로 s2mm까지
\draw[arr] (arr-s4.south) -- (arr-s4.south|-{(0,\lvlb)})
-- node[lbl,above,pos=0.2]{AXI4-S} (k2.east);
\draw[darr] (buf) -- (k1);
\draw[darr] (buf) -- (k2);
\begin{scope}[on background layer]
\node[psregion,fit=(ps),label={[grouplabel]above:PS}] {};
\node[plregion,fit=(k1)(k2)(buf),inner sep=8pt,label={[grouplabel]above:PL @ 300 MHz}] {};
\node[clkdomain,fit=(arr-box),inner sep=3pt,label={[grouplabel,text=hwaccent]above:AIE array $3\times4$ @ 1.25 GHz}] {};
\end{scope}
\end{tikzpicture}
패키지 소스
hwfig.sty (v1.1, Pelayo Leguina, [email protected], LPPL 1.3c)는 이 파일 옆에 제공됩니다. 변경 로그, 갤러리 및 예제는 공개 hwfig 저장소에 있으며, 이 스킬은 skill/ 아래에서 유지 관리되고 skill/package.sh로 패키징됩니다.