[Dépêche paru initialement sur LinuxFR]
Yosys est devenu le pivot opensource du développement des circuits intégrés FPGA et ASIC.
Le 27 septembre 2021 a été publiée la nouvelle version 0.10 de Yosys sur l’hébergeur de gestionnaire de versions GitHub.
Cette sortie tardive (la 0.9 date de 2019) est l’occasion de parler de ce logiciel libre de synthèse Verilog, pivot de la libération des FPGA (et des ASIC). Plutôt que de simplement présenter les changements nous allons présenter le logiciel et le principe de la synthèse «RTL».
Le manuel de Yosys représente les différentes couches d’abstractions utilisées en conception numérique.
Les couches «System Level» et «High Level» sont généralement des modèles écrits en C/C++/OpenCV/Matlab/… puis convertis en modèles «Behavioral» par un humain. Il existe quelques logiciels dit de «synthèse de haut niveau» qui permettent cette conversion en automatique, mais ça n’est pas la panacée, et (très) souvent verrouillé sur une seule marque de FPGA.
Le niveau «Behavioral» est celui dans lequel on décrit le comportement du composant en Verilog ou VHDL. Il est également possible aujourd’hui d’utiliser des langages comme Clash, Chisel ou Migen. Ces derniers généreront ensuite du code Verilog au niveau «RTL».
Comme son nom l’indique, la couche «RTL» est une description au niveau «transfert de registres». On y décrit le comportement des registres au rythme de l’horloge. Yosys utilise son propre langage nommé RTLIL pour cette étape, mais il est parfaitement possible d’utiliser Verilog ici.
Dans la couche «physique» on décrit le système au moyen de portes logiques disponibles dans le FPGA cible. À ce niveau on parlera souvent de «netlist». Cette netlist est souvent décrite au format EDIF, mais il est possible de la décrire en Verilog ou VHDL. Yosys propose également le format JSON bien connu des développeurs JavaScript.
Le niveau «switch level» n’est pas vraiment utilisé en synthèse sur FPGA. C’est la description des connexions entre transistors, elle ne fait pas vraiment de sens pour un FPGA dans la mesure où les cellules logiques sont figées dans le FPGA.
Arrivé au niveau portes (Physical Gate level) on quitte la synthèse – et donc yosys – pour passer à la mise en paquet (Pack), au placement puis au routage. Et on s’enfonce dans la jungle sombre et humide des logiciels gratuits-mais-pas-trop non libres fournis par les constructeurs. Il existe toutefois un logiciel libre nommé nextpnr, mais ça nous éloigne du sujet. Sachez juste que nextpnr est parfaitement utilisable pour certaines marques de FPGA (ICE40, Gowin, ECP5 notamment).
Yosys est un logiciel de synthèse Verilog, il prend en entrée un source Verilog dans la couche «Behavioral Level» pour descendre dans les couches jusqu’au niveau «Physical Gate».
commençons donc par l’exemple de l’inverseur synchrone suivant (fichier invert.v
):
// inverseur
module syncinvert(
input clock,
input reset,
input inval,
output outval);
reg regval;
assign outval = regval;
always@(posedge clock, posedge reset)
begin
if(reset)
regval <= 1'b0;
else
regval <= !inval;
end
endmodule
Par défault, Yosys se présente sous la forme d’une console «REPL» (Read Eval Print Loop) et se lance en tapant son nom :
$ yosys
/----------------------------------------------------------------------------\
| |
| yosys -- Yosys Open SYnthesis Suite |
| |
| Copyright (C) 2012 - 2020 Claire Xenia Wolf <claire@yosyshq.com> |
| |
| Permission to use, copy, modify, and/or distribute this software for any |
| purpose with or without fee is hereby granted, provided that the above |
| copyright notice and this permission notice appear in all copies. |
| |
| THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
| ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
| OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| |
\----------------------------------------------------------------------------/
Yosys 0.10+0 (git sha1 070cad5f4, clang 8.0.0-svn345496-1~exp1+0~20181029105533.852~1.gbpf10f36 -fPIC -Os)
yosys>
Premier changement de cette version : l’auteur n’est plus Clifford Wolf mais Claire Xenia Wolf. Si la date du début du copyright n’a pas changée c’est que les deux sont une seule et même personne, elle a «juste» changé de prénom et d’état civil.
La ligne de commande se comporte comme une ligne de commande shell classique, avec le rappel des commandes par flèche haut/bas, et la complétion avec Ctrl+R et tabulation.
On charge son fichier source verilog avec la commande read_verilog
.
yosys> read_verilog invert.v
1. Executing Verilog-2005 frontend: invert.v
Parsing Verilog input from `invert.v' to AST representation.
Generating RTLIL representation for module `\syncinvert'.
Successfully finished Verilog frontend.
Yosys nous informe ici qu’il a bien lu et analysé le fichier source. Le «gateware» est bien conforme au standard Verilog-2005 et a été converti dans le langage interne nommé RTLIL (RTL Intermediate Language).
On peut lister les modules chargés en mémoire grâce à la commande ls
.
yosys> ls
1 modules:
syncinvert
Et afficher une vue graphique du module avec show
:
yosys> show syncinvert
4. Generating Graphviz representation of design.
Writing dot description to `/home/fabien/.yosys_show.dot'.
Dumping module syncinvert to page 1.
Exec: { test -f '/home/user/.yosys_show.dot.pid' && fuser -s '/home/user/.yosys_show.dot.pid' 2> /dev/null; } || ( echo $$ >&3; exec xdot '/home/fabien/.yosys_show.dot'; ) 3> '/home/user/.yosys_show.dot.pid' &
Qui affiche l’image suivante
Cette simple lecture du fichier verilog nous a fait passer la première étape de la synthèse. Nous sommes presque descendus au niveau de la couche «RTL» de la synthèse. Presque, car il faut encore «mapper» la procédure que l’on voit au centre avec la commande proc
:
yosys> proc
10. Executing PROC pass (convert processes to netlists).
10.1. Executing PROC_CLEAN pass (remove empty switches from decision trees).
Cleaned up 0 empty switches.
10.2. Executing PROC_RMDEAD pass (remove dead branches from decision trees).
Removed a total of 0 dead cases.
10.3. Executing PROC_PRUNE pass (remove redundant assignments in processes).
Removed 0 redundant assignments.
Promoted 0 assignments to connections.
10.4. Executing PROC_INIT pass (extract init attributes).
10.5. Executing PROC_ARST pass (detect async resets in processes).
10.6. Executing PROC_MUX pass (convert decision trees to multiplexers).
10.7. Executing PROC_DLATCH pass (convert process syncs to latches).
10.8. Executing PROC_DFF pass (convert process syncs to FFs).
10.9. Executing PROC_MEMWR pass (convert process memory writes to cells).
10.10. Executing PROC_CLEAN pass (remove empty switches from decision trees).
Cleaned up 0 empty switches.
10.11. Executing OPT_EXPR pass (perform const folding).
Optimizing module syncinvert.
Le résultat ressemble beaucoup plus à la bascule D que l’on connaît.
On peut optimiser ce graphe avec la commande opt
, ce qui supprimera la branche inutile BUF -> $0\regval[0:0]
.
S’ensuit toute une série de commandes d’optimisation comme memory
pour détecter les tableaux et utiliser des blocs de ram si possible ou techmap
pour «mapper» les cellules d’une bibliothèque donnée.
yosys> opt; memory; opt; techmap; opt
Notez que toutes ces commandes étant des commandes d’optimisations, rien n’interdit de les relancer pour améliorer encore l’optimisation (ici les optimisation sont totalement inutiles vu la simplicité du schéma).
Beaucoup d’étapes dépendantes de la cible sont ensuite nécessaires pour obtenir une netlist correspondant au composant. Ces étapes étant différentes en fonction de l’architecture cible. Yosys inclut des scripts pour chaque composant supporté.
Par exemple, si nous voulons synthétiser pour icestick, le FPGA monté sur la carte est un ice40, nous pourrons donc utiliser le script nommé synth_ice40
:
yosys> synth_ice40
[...]
37.47. Printing statistics.
=== syncinvert ===
Number of wires: 6
Number of wire bits: 6
Number of public wires: 6
Number of public wire bits: 6
Number of memories: 0
Number of memory bits: 0
Number of processes: 0
Number of cells: 2
SB_DFFR 1
SB_LUT4 1
37.48. Executing CHECK pass (checking for obvious problems).
Checking module syncinvert...
Found and reported 0 problems.
Le lecteur attentif reconnaîtra la LUT 4 entrées et la basculeD de l’ICE40 dans le schéma généré :
Pour connaitre les scripts de synthèse disponibles dans yosys il suffit d’utiliser la complétion de commande avec synth_
:
yosys> synth_<TAB>
synth_achronix synth_coolrunner2 synth_ecp5 synth_gowin synth_ice40 synth_intel_alm synth_nexus synth_sf2
synth_anlogic synth_easic synth_efinix synth_greenpak4 synth_intel synth_machxo2 synth_quicklogic synth_xilinx
Ce qui nous donne 16 modèles de FPGA supporté «officiellement» par Yosys.
Il n’est pas obligatoire d’avoir un script synth_
pour pouvoir synthétiser pour un modèle de FPGA du moment que l’on fournit la bibliothèque des primitives. Pepijn De Vos s’est par exemple amusé à synthétiser vers une bibliothèque de composants en logique discrète (la série des 74-* pour ceux qui connaissent un peu l’électronique). Il a ensuite produit, assemblé et soudé la carte électronique correspondante.
Mais! Pepijn est parti d’un gateware écrit en VHDL ! En quoi cela concerne-t-il yosys qui est censé être un logiciel de synthèse Verilog ?
Pepijn a utilisé pour cela une extension de yosys permettant de se connecter au logiciel GHDL. Avec cette extension (encore en bêta mais déjà bien avancée), le VHDL est décodé avec GHDL qui transmet ensuite les informations à Yosys pour la synthèse. Et comme yosys est capable de sortir une version verilog de sa représentation interne RTLIL, on peut s’en servir pour faire de la conversion VHDL->Verilog sans problème.
Notre inverseur est désormais synthétisé. Nous pouvons donc l’enregistrer au format de notre choix pour passer ensuite au placement routage.
On peut l’écrire au format Verilog par exemple si nous souhaitons le simuler ou tout simplement lire la netlist :
yosys> write_verilog invert_synth.v
41. Executing Verilog backend.
Dumping module `\syncinvert'.
Ce qui donnera les sources suivantes :
/* Generated by Yosys 0.10+0 (git sha1 070cad5f4, clang 8.0.0-svn345496-1~exp1+0~20181029105533.852~1.gbpf10f36 -fPIC -Os) */
(* top = 1 *)
(* src = "invert.v:2.1-19.10" *)
module syncinvert(clock, reset, inval, outval);
(* src = "invert.v:3.11-3.16" *)
input clock;
(* src = "invert.v:5.11-5.16" *)
input inval;
(* src = "invert.v:6.12-6.18" *)
output outval;
(* src = "invert.v:7.5-7.11" *)
wire regval;
(* src = "invert.v:11.1-17.4" *)
wire regval_SB_DFFR_Q_D;
(* src = "invert.v:4.11-4.16" *)
input reset;
(* module_not_derived = 32'd1 *)
(* src = "/usr/local/bin/../share/yosys/ice40/cells_map.v:12.34-13.52" *)
SB_LUT4 #(
.LUT_INIT(16'h00ff)
) inval_SB_LUT4_I3 (
.I0(1'h0),
.I1(1'h0),
.I2(1'h0),
.I3(inval),
.O(regval_SB_DFFR_Q_D)
);
(* module_not_derived = 32'd1 *)
(* src = "invert.v:11.1-17.4|/usr/local/bin/../share/yosys/ice40/ff_map.v:9.57-9.103" *)
SB_DFFR regval_SB_DFFR_Q (
.C(clock),
.D(regval_SB_DFFR_Q_D),
.Q(regval),
.R(reset)
);
assign outval = regval;
endmodule
Les sources sont annotées avec des références au verilog initial. On repère bien la bascule SB_DFFR et la SB_LUT4 avec sa configuration.
Et dans la mesure du possible, les noms de registres ont été gardés, ce qui rend le fichier assez facile à lire.
Pour le placement routage, si on utilise nextpnr il faudra «sortir» au format json :
yosys> write_json invert.json
42. Executing JSON backend.
Le fichier invert.json
est beaucoup plus large que la sortie verilog (9779 lignes).
Les différents formats de sortie disponibles sont visibles avec la complétion de commande write_
:
yosys> write_<TAB>
write_aiger write_btor write_edif write_firrtl write_intersynth write_rtlil write_smt2 write_spice write_verilog
write_blif write_cxxrtl write_file write_ilang write_json write_simplec write_smv write_table write_xaiger
Cette possibilité de convertir dans différents formats le verilog initial fait de Yosys le couteau suisse du gateware. On peut s’en servir pour faire de la synthèse à destination des FPGA bien sûr, mais il est possible de «mapper» sur d’autres bibliothèques pour faire des PCB «discret» comme on l’a vu avec Pepijn De Vos.
Il est également possible de faire de la synthèse à destination des ASIC. Yosys est d’ailleurs utilisé par la chaîne de développement opensource OpenLane.
Enfin, les modèles synthétisés par yosys peuvent servir à faire de la preuve formelle, à partir de sources verilog mais également VHDL.
En règle générale, il n’est pas nécessaire de connaître les détails des commandes de Yosys. L’utilisation de yosys est enfouie dans les scripts et autres Makefile des outils utilisés.
Bref, en quelques années, Yosys est devenu le pivot opensource du développement FPGA et ASIC. Il méritait bien une dépêche sur LinuxFr.org !