Archives quotidiennes :

Sortie de la version 0.10 de Yosys

[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.

Couche d’abstraction utilisées en synthèse 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

Rendu xdot de l’inverseur

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.

Rendu xdot de l’inverseur «mappé»

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
Rendu xdot de l’inverseur mappé avec `techmap`

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é :

Rendu xdot de l’inverseur synthétisé pour ICE40

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 !