Figures TikZ matériel (hwfig v1.1)
Utilisez cette compétence chaque fois que l'utilisateur souhaite une figure matérielle en LaTeX/TikZ : flux de données d'un noyau HLS/FPGA, une couche de réseau de neurones quantifiée, un schéma de SoC Versal/Zynq, des réseaux AI Engine, des réseaux systoliques, des arbres d'addition, des pipelines, des NoCs, des hiérarchies mémoire, des domaines d'horloge, des floorplans. La sortie est toujours un source TikZ éditable ainsi qu'un aperçu compilé PDF/PNG.
Flux de travail
- Obtenir le package. Copiez
hwfig.stydu répertoire de base de cette compétence dans le répertoire de travail (sauf si l'utilisateur en a déjà une copie — si la sienne n'a pasv1.1dans sa ligne\ProvidesPackage, proposez de la mettre à jour). Lisez le fichier et copiez-le octet par octet ; ne le retapez jamais et ne redéfinissez pas les styles en ligne — les palettes ne fonctionnent qu'à travers les couleurs de rôle. - Choisir une palette (par défaut
grey), soit comme option de package\usepackage[okabe]{hwfig}soit avec\hwpalette{...}n'importe où (locale à un groupe, donc par figure) :grey— par défaut pour impression / revue, reflète le modèle de référence (boîtes de calcul blanches, quantifieurs gris, constantes grises en pointillés).okabe— Okabe–Ito, adapté aux daltoniens, plus fort contraste. Bon choix par défaut pour les articles en couleur.tol— Paul Tol muted, adapté aux daltoniens, plus doux.nord— tons froids, pour les diapositives.slate— bleu-gris + mauve + corail, correspond aux présentations scientifiques. Si l'utilisateur ne précise pas, produisezgreyet proposez une palette couleur ; pour comparer, compilez la même figure avec plusieurs palettes (la boucle\foreach \pal in {grey,okabe,...}{\hwpalette{\pal}...}dans un documentstandalonedonne une page par palette). Un nom de palette inconnu est une erreur fatale.
- Esquisser d'abord la disposition sur une grille (coordonnées
at (x,y)explicites, pas de colonne ~2.4 cm, rangées ±1.4 cm), puis câbler. Les coordonnées explicites sont préférables àpositioningpour les figures de flux de données denses. - Compiler en tant que
\documentclass[tikz,border=4pt]{standalone}+\usepackage{hwfig}avecpdflatex -interaction=batchmode -halt-on-error(avec un délai d'attente ;nonstopmodepeut bloquer), pixelliser avecpdftoppm -r 110 -png, regarder le PNG, et corriger les chevauchements (étiquettes sur les fils, fils traversant des boîtes, titres qui se chevauchent, étiquettes de cadre touchant des nœuds) avant de livrer. Itérer jusqu'à ce que ce soit propre. - Livrer le
.tex(corps de la figure prêt à être collé dans un article), le.styet le PDF. Rappeler à l'utilisateur que dans son article, il a besoin de\usepackage{hwfig}(ou\usepackage[<palette>]{hwfig}).
Grammaire visuelle (rester cohérent)
- Les données circulent de gauche à droite ; le chemin principal se trouve sur un axe horizontal, les branches parallèles au-dessus/au-dessous (±1.4 cm).
- Les constantes de compilation (
ctime, boîte en pointillés) se placent directement au-dessus/au-dessous du bloc qu'elles configurent et se connectent avecdarr(flèche en pointillés). - Chaque bloc de calcul qui change de précision est suivi d'un
qbox(requantification/décalage/saturation). - Les branches fusionnent en un nœud
opavec des fils à angle droit qui arrivent verticalement :\draw[arr] (qr.east) -| ($(sum.north)+(0,0.32)$) -- (sum.north); - Branches alternatives à partir d'une source : une coordonnée de bifurcation avec un point,
\fill[hwwire] (fork) circle (1.3pt);, puis des coudes|-vers chaque branche. - Utilisez
hotpour le chemin critique / mis en évidence,buspour les chemins de données larges avecpic[pos=.5]{buswidth=512},node[lbl,midway,above]{AXI4-S}pour les noms de protocole (lblboxlorsque l'étiquette doit se trouver sur des fils qui se croisent). - Les cadres de regroupement vont sur la couche d'arrière-plan avec
fit:\begin{scope}[on background layer]\node[group,fit=(a)(b),label={[grouplabel]above:PL}] {};\end{scope} - Domaines d'horloge :
clkdomain(couleur d'accentuation, en pointillés) ouclkdomain=<color>; marquez les traversées avec un nœudcdc. - Commencez chaque image par
\begin{tikzpicture}[hw](définit la police\footnotesize, l'épaisseur de ligne, les pointes de flèche).
Routage et étiquettes (vérifiez-les sur chaque PNG)
- Espaces entre les régions. Laissez ≥ 0.6 cm entre les cadres adjacents (Runtime | Message passing, PL | AIE). Les nœuds, les
opde fusion et les fils ne doivent jamais se trouver sur un bord de cadre — si un nœud n'appartient à aucun des deux cadres, donnez-lui de l'espace à l'extérieur des deux. - Canaux de routage. Les fils entre les régions circulent dans un canal vide entre les cadres (définissez-le :
\def\chan{6.7}), puis sur leur propre niveau horizontal en dessous/au-dessus du cadre cible (\def\lvla{-1.7}). Deux fils ne partagent jamais un niveau ; gardez ≥ 0.3 cm entre un fil et tout bord de cadre ou côté de bloc parallèle, et ≥ 0.4 cm entre des fils parallèles. - Les étiquettes se placent uniquement sur les segments libres. Mettez
lbl/buswidthsur un segment qui se trouve entièrement dans un espace vide — jamais là où le fil traverse une bordure de cadre, et jamais à moins de ~0.2 cm d'un bloc. Si la seule étendue libre est verticale, faites pivoter l'étiquette pour qu'elle se lise de bas en haut :node[lbl,rotate=90,below]{AXI4-S}. Sur les liens courts, utilisezpic[pos=.35..0.4]pour que le nombre dégage le bloc de destination. - Segments explicites pour les coudes étiquetés.
-|/|-ne peut pas prendre d'étiquette sur une branche choisie ; écrivez les coins :(a.east) -- (\chan,ya) -- node[lbl,...]{X} (\chan,\lvla) -- (b.south|-{(0,\lvla)}) -- (b.south); - Mathématiques dans les étiquettes :
$W_{\mathrm{root}}$; étiquettes sur deux lignes avec\\(tous les styles définissentalign=center).
Styles de nœuds (tous conscients de la palette)
| style | utilisation |
|---|---|
runtime | entrées/sorties d'exécution, ports, tenseurs |
ctime | constantes de compilation : poids, échelles, configuration |
hlsbox | noyau de calcul / fonction HLS / noyau AIE |
qbox | quantifieur, requantification, décalage+sat |
op | +, ×, max (cercle) |
mux, demux | multiplexeur (entrées à l'ouest, sortie à l'est) / démultiplexeur (miroir) |
mem, bram, uram | tampons sur puce |
fifo | flux/FIFO |
reg / ff | registre avec encoche d'horloge |
lut, dsp | primitives FPGA (dsp place une petite étiquette "DSP" à l'extérieur de son coin supérieur droit — laissez de l'espace) |
extmem | DDR / HBM (cylindre) |
cpu | PS / ARM / RISC-V (cadre double) |
host | CPU hôte (côté PCIe) |
xbar | interconnexion AXI / barre NoC (\rotatebox{90}{AXI IC}) |
router | routeur/commutateur NoC (losange) |
pe | élément de traitement |
aie | tuile AI Engine (cœur + mémoire locale ; étiquette centrée sur le cœur) |
chip | boîtier/puce avec broches |
port | petit marqueur de broche |
cdc | synchroniseur de traversée de domaine d'horloge |
group, plregion, psregion, clkdomain | cadres d'arrière-plan |
grouplabel, lbl, lblbox | titres de cadre, étiquettes de fil (lblbox = fond blanc) |
Styles de bords : arr, darr, bus, hot. Repère de bus : pic[pos=.5]{buswidth=32} (nombre à droite du repère) ou buswidth'=32 (à gauche).
Pics paramétriques
Passez les options par pic — elles restent locales à ce pic, donc différentes tailles peuvent partager une image :
\pic (A) at (0,0) {aiearray={rows=2,cols=4}};. \hwset{key=value,...} définit les valeurs par défaut pour le reste de la portée courante à la place. Les nœuds internes sont adressables en tant que (name-...).
| pic | clés | parties adressables |
|---|---|---|
aiearray | rows, cols, dx, dy, tilelabel | tuiles (n-t<r>-<c>) (r=1 en bas), shims (n-s<c>), cadre (n-box) |
systolic | rows, cols | (n-pe<r>-<c>) (r=1 en haut) |
addertree | depth (2^depth entrées) | entrées (n-in<k>), additionneurs (n-a<level>-<k>), sortie (n-out) |
pipeline | labels={Load,MAC,Requant,...} | étages (n-st<k>), registres (n-r<k>) |
noc | rows, cols, nocpe (vrai/faux) | routeurs (n-n<r>-<c>), PEs (n-pe<r>-<c>) |
fabric | columns={I,C,C,D,C,B,...}, fabricrows (n'importe quelle valeur) | sommets de colonne (n-c<k>). C=CLB D=DSP B=BRAM U=URAM I=IO |
legend | legend={comp/Compute,mem/BRAM,...} (rôles : io comp quant const op mem ctrl group) ; espacement automatique | — |
Routez les fils autour des pics (par exemple, dans les tuiles shim par le bas : (k1.east) -- ++(0.9,0) |- ($(arr-s1.south)+(0,-0.35)$) -- (arr-s1.south)), jamais à travers les tuiles.
Palettes personnalisées
Aucun interne @ nécessaire — définissez les 8 rôles (trait, remplissage) et les trois couleurs de fil :
\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}} % fil, fil constant, accent/chaud
\hwpalette{mine}
Gardez les remplissages ≤ 25% de teinte pour que le texte noir reste lisible, et vérifiez que la conversion en niveaux de gris sépare toujours les rôles.
Pièges
- Écrivez les fichiers
.texavec l'outil d'écriture de fichiers, pas avec des heredocs shell,sedou des chaînes littérales Python : ceux-ci transforment systématiquement\\en\(ou\c...en caractères de contrôle) et cassent les sauts de ligne dans le texte des nœuds. - Un deux-points ou une virgule dans le texte
label=casse l'analyse syntaxique des clés — mettez-le entre accolades :label={[grouplabel]above:{INT8: shifts}}. - Une liste
fit=ne peut pas contenir($(a)+(1,2)$)(la virgule divise la liste) ; définissez d'abord une\coordinatenommée. - Pour une ligne supplémentaire dans un nœud, utilisez un nœud simple avec
align=centeret\\[-2pt]{\tiny ...}— ne superposez pas une deuxième étiquette sur la boîte. shapes.geometrictrapeziumavec du texte vide divise par zéro — c'est pourquoimux/demuxsont des images de chemin personnalisées ; ne les remplacez pas.- Dans
\foreach, utilisez\pgfmathtruncatemacropour l'arithmétique entière avant d'utiliser les valeurs dans les noms de nœuds ; dans\foreach \a/\b in {...}un/dans le texte de l'étiquette divise (écrivezPort, pasI/O). clkdomaina un remplissage léger ; passezfill=nonelorsque vous le dessinez sur unfabricou un autre contenu dense.- MiKTeX ignore
TEXINPUTSde style POSIX ; gardezhwfig.styà côté du.tex(ou passez--include-directory=<windows path>). - Gardez les figures ≤ ~16 cm de large pour un article à deux colonnes en
\footnotesize; mettez à l'échelle avec\resizebox{\linewidth}{!}{...}seulement en dernier recours.
Exemple de référence (couche GNN, le modèle de base)
\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) {Racine\\$W_{\mathrm{root}}x_i$};
\node[qbox] (qr) at (4.9,1.4) {$Q_r$\\décalage + sat8};
\node[mem] (agg) at (2.5,-1.4) {Agrégation moyenne\\$m_i$};
\node[hlsbox] (neigh) at (5.5,-1.4) {Voisins\\$W_{\mathrm{neigh}}m_i+b$};
\node[qbox] (qn) at (8.1,-1.4) {$Q_n$\\décalage + 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) {Couche 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:Passage de messages}] {};
\end{scope}
\end{tikzpicture}
Exemple de référence (SoC Versal)
\begin{tikzpicture}[hw]
\node[host] (host) at (-3.4,0.3) {Hôte\\(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) {Buf BRAM};
\pic (arr) at (8.3,0.1) {aiearray};
% niveaux de routage
\def\chan{6.7} % canal vertical entre les régions PL et AIE
\def\lvla{-1.7} % mm2s -> AIE, sous le cadre AIE
\def\lvlb{-2.3} % AIE -> s2mm, un niveau plus bas (= rangée 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 -> shim 1 : directement dans le canal, en bas, le long du niveau a, en haut dans le 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 : en bas jusqu'au niveau b, à gauche jusqu'à 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:Réseau AIE $3\times4$ @ 1.25 GHz}] {};
\end{scope}
\end{tikzpicture}
Source du package
hwfig.sty (v1.1, par Pelayo Leguina, [email protected], LPPL 1.3c) est distribué à côté de ce fichier. Le journal des modifications, la galerie et les exemples vivent dans le dépôt public hwfig ; cette compétence y est maintenue sous skill/ et empaquetée avec skill/package.sh.