TikZ hardware figures (hwfig v1.1)
このスキルは、ユーザーがLaTeX/TikZでハードウェア図(HLS/FPGAカーネルのデータフロー、量子化NN層、Versal/Zynq SoCのブロック図、AIエンジンアレイ、シストリックアレイ、加算木、パイプライン、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を生成し、1つのカラーパレットを提案します。比較するには、同じ図を複数のパレットでコンパイルします(standaloneドキュメント内で\foreach \pal in {grey,okabe,...}{\hwpalette{\pal}...}とループさせると、1ページに1パレットずつ表示されます)。未知のパレット名はハードエラーです。
- 最初にグリッド上にレイアウトをスケッチする(明示的な
at (x,y)座標、カラムピッチ約2.4cm、行間±1.4cm)。その後配線します。密なデータフロー図には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); - 1つのソースからの代替ブランチ:ドットのあるフォーク座標、
\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})。2本の配線が同じレベルを共有することはありません。配線と平行なフレーム端またはブロック側面の間は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}}$;2行ラベルは\\を使用(すべてのスタイルは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エンジンタイル(コア+ローカルメモリ。ラベルはコアの中央) |
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にローカルに留まるため、異なるサイズでピクチャを共有できます:
\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 (真/偽) | ルーター (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,...} (ロール: io comp quant const op mem ctrl group); 自動スペーシング | — |
配線はpicの周りを通過させ(例:下からシムタイルに入る:(k1.east) -- ++(0.9,0) |- ($(arr-s1.south)+(0,-0.35)$) -- (arr-s1.south))、タイルを通り抜けさせないでください。
カスタムパレット
@内部は不要です。8つのロール(描画、塗りつぶし)すべてと3つの配線色を設定します:
\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 ...}で使用します。ボックスに2つ目のラベルを重ねないでください。 shapes.geometricのtrapeziumを空のテキストで使用するとゼロ除算になります。そのため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>を渡す)、TEXINPUTS環境変数を使用しないでください。 - 図は2段組みの論文で
\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、1レベル下(= 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でパッケージ化されています。