CommunityRecherche & Datenanalysegithub.com

pleguina/tikz-hardware-figures

Erstellen Sie publizierbare Hardware/FPGA/Datenfluss-Blockschaltbilder in TikZ (HLS-Kerne, AIE-Arrays, systolische Arrays, SoCs, Pipelines) in Graustufen oder farbenblindsicheren Paletten.

Was ist tikz-hardware-figures?

Dieses Skill ermöglicht die Erstellung professioneller Hardware-Blockschaltbilder in LaTeX/TikZ, wie Datenflüsse von HLS/FPGA-Kernen, quantisierten NN-Schichten, Versal/Zynq-SoC-Blockdiagrammen, AI-Engine-Arrays, systolischen Arrays, Addierbäumen, Pipelines, NoCs, Speicherhierarchien, Taktbereichen und Floorplans. Es unterstützt die lokale LaTeX-Palette `hwfig.sty` (v1.1) und stellt sicher, dass die Ausgabe immer als bearbeitbarer TikZ-Quellcode mit einer kompilierten PDF/PNG-Vorschau erfolgt. Das Skill bietet eine klare visuelle Grammatik mit definierten Knoten- und Kantenstilen, die konsistent verwendet werden müssen, sowie vorgefertigte parametrische `pic`s (z.B. `aiearray`, `systolic`, `addertree`). Es enthält außerdem integrierte Farbpaletten (grau, okabe, tol, nord, slate), die farbenblindsicher sind, und detaillierte Richtlinien für Routing, Beschriftung und das Vermeiden häufiger Fehler. Entwickelt für den Einsatz mit Claude Code, Cursor, Codex und ähnlichen KI-Agenten, die LaTeX/TikZ-Code generieren.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/pleguina/hwfig/tree/HEAD/skill

Installed? Explore more Recherche & Datenanalyse skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

TikZ-Hardwarefiguren (hwfig v1.1)

Verwenden Sie dieses Skill, wenn der Benutzer eine Hardwarefigur in LaTeX/TikZ wünscht: Datenfluss eines HLS/FPGA-Kerns, einer quantisierten NN-Schicht, eines Versal/Zynq-SoC-Blockschaltbilds, AI-Engine-Arrays, systolischer Arrays, Addierbäume, Pipelines, NoCs, Speicherhierarchien, Taktbereiche, Floorplans. Die Ausgabe ist immer ein editierbarer TikZ-Quellcode plus eine kompilierte PDF/PNG-Vorschau.

Arbeitsablauf

  1. Paket besorgen. Kopieren Sie hwfig.sty aus dem Basisverzeichnis dieses Skills in das Arbeitsverzeichnis (es sei denn, der Benutzer hat bereits eine Kopie – wenn seine keine v1.1 in der \ProvidesPackage-Zeile enthält, bieten Sie ein Update an). Lesen Sie die Datei und kopieren Sie sie byteweise; geben Sie sie niemals von Hand ein oder definieren Sie die Stile direkt neu – die Paletten funktionieren nur über die Rollenfarben.
  2. Palette auswählen (Standard grey), entweder als Paketoption \usepackage[okabe]{hwfig} oder mit \hwpalette{...} an beliebiger Stelle (gruppenlokal, also pro Figur):
    • grey – Standard für Druck/Zeitschriften, spiegelt die Referenzvorlage wider (weiße Rechenblöcke, graue Quantisierer, gestrichelte graue Konstanten).
    • okabe – Okabe–Ito, farbenblindsicher, stärkster Kontrast. Gute Standardeinstellung für Farbpapiere.
    • tol – Paul Tol muted, farbenblindsicher, weicher.
    • nord – kühle Töne, für Folien.
    • slate – Blaugrau + Malve + Koralle, passend zu wissenschaftlichen Folien. Wenn der Benutzer keine Angabe macht, erstellen Sie grey und schlagen Sie eine Farbpalette vor; zum Vergleichen kompilieren Sie dieselbe Figur in mehreren Paletten (Schleife \foreach \pal in {grey,okabe,...}{\hwpalette{\pal}...} innerhalb eines standalone-Dokuments ergibt eine Seite pro Palette). Ein unbekannter Palettenname ist ein schwerer Fehler.
  3. Skizzieren Sie das Layout zuerst auf einem Raster (explizite at (x,y)-Koordinaten, ~2.4 cm Spaltenabstand, ±1.4 cm Reihen), dann verdrahten. Explizite Koordinaten sind für dichte Datenflüsse besser als positioning.
  4. Kompilieren als \documentclass[tikz,border=4pt]{standalone} + \usepackage{hwfig} mit pdflatex -interaction=batchmode -halt-on-error (mit Timeout; nonstopmode kann hängen bleiben), rastern mit pdftoppm -r 110 -png, PNG ansehen und Überlappungen (Beschriftungen auf Leitungen, Leitungen über Blöcken, kollidierende Titel, Rahmenbeschriftungen, die Knoten berühren) vor der Auslieferung beheben. Wiederholen, bis alles sauber ist.
  5. Liefern Sie die .tex (Figuren-Body, bereit zum Einfügen in ein Paper), die .sty und das PDF. Erinnern Sie den Benutzer daran, dass er in seinem Paper \usepackage{hwfig} (oder \usepackage[<palette>]{hwfig}) verwenden muss.

Visuelle Grammatik (konsistent halten)

  • Datenfluss links → rechts; der Hauptpfad liegt auf einer horizontalen Achse, parallele Äste oben/unten (±1.4 cm).
  • Kompilierzeitkonstanten (ctime, gestrichelte Box) liegen direkt über/unter dem Block, den sie konfigurieren, und verbinden sich mit darr (gestrichelter Pfeil).
  • Jeder Rechenblock, der die Genauigkeit ändert, wird von einem qbox (Requant/Shift/Saturate) gefolgt.
  • Äste werden in einem op-Knoten zusammengeführt, wobei die Leitungen vertikal ankommen: \draw[arr] (qr.east) -| ($(sum.north)+(0,0.32)$) -- (sum.north);
  • Alternative Äste von einer Quelle: eine Gabelungskoordinate mit einem Punkt, \fill[hwwire] (fork) circle (1.3pt);, dann |--Knicke zu jedem Ast.
  • Verwenden Sie hot für den kritischen/hervorgehobenen Pfad, bus für breite Datenpfade mit pic[pos=.5]{buswidth=512}, node[lbl,midway,above]{AXI4-S} für Protokollnamen (lblbox, wenn die Beschriftung über kreuzenden Leitungen liegen muss).
  • Gruppierungsrahmen gehen auf die Hintergrundebene mit fit: \begin{scope}[on background layer]\node[group,fit=(a)(b),label={[grouplabel]above:PL}] {};\end{scope}
  • Taktbereiche: clkdomain (Akzentfarbe, gestrichelt) oder clkdomain=<color>; Kreuzungen mit einem cdc-Knoten markieren.
  • Beginnen Sie jedes Bild mit \begin{tikzpicture}[hw] (setzt Schrift \footnotesize, Linienbreite, Pfeilspitzen).

Routing und Beschriftungen (bei jedem PNG prüfen)

  • Abstände zwischen Bereichen. Lassen Sie ≥ 0.6 cm zwischen benachbarten Rahmen (Runtime | Message Passing, PL | AIE). Knoten, Merge-ops und Leitungen dürfen niemals auf einer Rahmenkante sitzen – wenn ein Knoten zu keinem der Rahmen gehört, geben Sie ihm Platz außerhalb beider.
  • Routing-Kanäle. Leitungen zwischen Bereichen laufen in einem leeren Kanal zwischen den Rahmen (definieren: \def\chan{6.7}), dann auf einer eigenen horizontalen Ebene unter/über dem Zielrahmen (\def\lvla{-1.7}). Zwei Leitungen teilen sich nie eine Ebene; halten Sie ≥ 0.3 cm zwischen einer Leitung und einer parallelen Rahmenkante oder Blockseite und ≥ 0.4 cm zwischen parallelen Leitungen.
  • Beschriftungen nur auf freien Segmenten. Setzen Sie lbl/buswidth auf ein Segment, das vollständig im leeren Raum liegt – niemals dort, wo die Leitung eine Rahmengrenze kreuzt, und niemals innerhalb von ~0.2 cm eines Blocks. Wenn der einzige freie Abschnitt vertikal ist, drehen Sie die Beschriftung, sodass sie von unten nach oben gelesen wird: node[lbl,rotate=90,below]{AXI4-S}. Bei kurzen Verbindungen verwenden Sie pic[pos=.35..0.4], damit die Nummer den Zielblock freigibt.
  • Explizite Segmente für beschriftete Knicke. -|/|- kann keine Beschriftung auf einem gewählten Schenkel aufnehmen; schreiben Sie die Ecken aus: (a.east) -- (\chan,ya) -- node[lbl,...]{X} (\chan,\lvla) -- (b.south|-{(0,\lvla)}) -- (b.south);
  • Mathematik in Beschriftungen: $W_{\mathrm{root}}$; zweizeilige Beschriftungen mit \\ (alle Stile setzen align=center).

Knotenstile (alle palettenbewusst)

StilVerwendung
runtimeLaufzeit-Eingaben/Ausgaben, Ports, Tensoren
ctimeKompilierzeitkonstanten: Gewichte, Skalen, Konfiguration
hlsboxRechenkern / HLS-Funktion / AIE-Kern
qboxQuantisierer, Requant, Shift+Sat
op+, ×, max (Kreis)
mux, demuxMultiplexer (Eingänge West, Ausgang Ost) / Demultiplexer (gespiegelt)
mem, bram, uramOn-Chip-Puffer
fifoStream/FIFO
reg / ffRegister mit Taktsymbol
lut, dspFPGA-Primitive (dsp platziert einen kleinen „DSP"-Tag außerhalb seiner oberen rechten Ecke – Platz lassen)
extmemDDR / HBM (Zylinder)
cpuPS / ARM / RISC-V (Doppelrahmen)
hostHost-CPU (PCIe-Seite)
xbarAXI-Interconnect / NoC-Bar (\rotatebox{90}{AXI IC})
routerNoC-Router/Switch (Raute)
peVerarbeitungselement
aieAI-Engine-Tile (Kern + lokaler Speicher; Beschriftung zentriert auf dem Kern)
chipGehäuse/Die mit Pins
portkleiner Pin-Marker
cdcTaktbereichsübergreifender Synchronisierer
group, plregion, psregion, clkdomainHintergrundrahmen
grouplabel, lbl, lblboxRahmentitel, Leitungsbeschriftungen (lblbox = weißer Hintergrund)

Kantenstile: arr, darr, bus, hot. Bus-Tick: pic[pos=.5]{buswidth=32} (Zahl rechts vom Tick) oder buswidth'=32 (links).

Parametrische Pics

Optionen pro Pic übergeben – sie bleiben lokal für dieses Pic, sodass verschiedene Größen ein Bild teilen können: \pic (A) at (0,0) {aiearray={rows=2,cols=4}};. \hwset{key=value,...} setzt stattdessen Standardwerte für den Rest des aktuellen Bereichs. Innere Knoten sind adressierbar als (name-...).

PicSchlüsselAdressierbare Teile
aiearrayrows, cols, dx, dy, tilelabelTiles (n-t<r>-<c>) (r=1 unten), Shims (n-s<c>), Rahmen (n-box)
systolicrows, cols(n-pe<r>-<c>) (r=1 oben)
addertreedepth (2^depth Eingänge)Eingänge (n-in<k>), Addierer (n-a<level>-<k>), Ausgang (n-out)
pipelinelabels={Load,MAC,Requant,...}Stufen (n-st<k>), Register (n-r<k>)
nocrows, cols, nocpe (true/false)Router (n-n<r>-<c>), PEs (n-pe<r>-<c>)
fabriccolumns={I,C,C,D,C,B,...}, fabricrows (beliebiger Wert)Spaltenköpfe (n-c<k>). C=CLB D=DSP B=BRAM U=URAM I=IO
legendlegend={comp/Compute,mem/BRAM,...} (Rollen: io comp quant const op mem ctrl group); automatisch beabstandet—

Leitungen um Pics herumführen (z.B. von unten in Shim-Tiles: (k1.east) -- ++(0.9,0) |- ($(arr-s1.south)+(0,-0.35)$) -- (arr-s1.south)), niemals durch Tiles.

Benutzerdefinierte Paletten

Keine @-Interna erforderlich – setzen Sie alle 8 Rollen (Draw, Fill) und die drei Leitungsfarben:

\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}}   % Leitung, Konstanten-Leitung, Akzent/hervorgehoben
\hwpalette{mine}

Füllungen ≤ 25 % Farbtiefe halten, damit schwarzer Text lesbar bleibt, und die Graustufenkonvertierung prüfen, ob die Rollen noch unterscheidbar sind.

Fallstricke

  • Schreiben Sie .tex-Dateien mit dem Dateischreibwerkzeug, nicht mit Shell-Heredocs, sed oder Python-String-Literalen: Diese verwandeln \\ oft in \ (oder \c... in Steuerzeichen) und zerstören Zeilenumbrüche im Knotentext.
  • Ein Doppelpunkt oder Komma innerhalb von label=-Text unterbricht die Schlüsselanalyse – klammern Sie ihn: label={[grouplabel]above:{INT8: shifts}}.
  • Eine fit=-Liste kann nicht ($(a)+(1,2)$) enthalten (das Komma teilt die Liste); definieren Sie zuerst eine benannte \coordinate.
  • Für eine zusätzliche Zeile innerhalb eines Knotens verwenden Sie einen einfachen Knoten mit align=center und \\[-2pt]{\tiny ...} – überlagern Sie keine zweite Beschriftung auf der Box.
  • shapes.geometric trapezium mit leerem Text führt zu einer Division durch Null – deshalb sind mux/demux benutzerdefinierte Pfadbilder; tauschen Sie sie nicht zurück.
  • Verwenden Sie innerhalb von \foreach \pgfmathtruncatemacro für ganzzahlige Arithmetik, bevor Sie Werte in Knotennamen verwenden. In \foreach \a/\b in {...} teilt ein / innerhalb des Beschriftungstextes ihn (schreiben Sie Port, nicht I/O).
  • clkdomain hat eine helle Füllung; übergeben Sie fill=none, wenn Sie es über einem fabric oder anderen dichten Inhalten zeichnen.
  • MiKTeX ignoriert POSIX-TEXINPUTS; behalten Sie hwfig.sty neben der .tex (oder übergeben Sie --include-directory=<windows path>).
  • Halten Sie Figuren ≤ ~16 cm breit für ein zweispaltiges Paper bei \footnotesize; skalieren Sie mit \resizebox{\linewidth}{!}{...} nur als letztes Mittel.

Referenzbeispiel (GNN-Schicht, die Hausvorlage)

\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}

Referenzbeispiel (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};

  % routing levels
  \def\chan{6.7}    % vertical channel between PL and AIE regions
  \def\lvla{-1.7}   % mm2s -> AIE, under the AIE frame
  \def\lvlb{-2.3}   % AIE -> s2mm, one level lower (= s2mm row)

  \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 -> shim 1: right into the channel, down, along level a, up into the shim
  \draw[arr] (k1.east) -- (\chan,1.6)
       -- node[lbl,rotate=90,below]{AXI4-S} (\chan,\lvla)
       -- (arr-s1.south|-{(0,\lvla)}) -- (arr-s1.south);
  % shim 4 -> s2mm: down to level b, left to 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}

Paketquelle

hwfig.sty (v1.1, von Pelayo Leguina, [email protected], LPPL 1.3c) befindet sich neben dieser Datei. Changelog, Galerie und Beispiele leben im öffentlichen hwfig-Repository; dieses Skill wird dort unter skill/ gepflegt und mit skill/package.sh verpackt.

Verwandte Skills