{"id":1007,"date":"2017-03-27T14:24:20","date_gmt":"2017-03-27T12:24:20","guid":{"rendered":"http:\/\/www.fabienm.eu\/wordpress\/?p=1007"},"modified":"2017-03-27T16:44:35","modified_gmt":"2017-03-27T14:44:35","slug":"comment-indiquer-la-version-de-son-projet-dans-le-bitstream-vivado","status":"publish","type":"post","link":"http:\/\/www.fabienm.eu\/wordpress\/2017\/03\/27\/comment-indiquer-la-version-de-son-projet-dans-le-bitstream-vivado\/","title":{"rendered":"Comment indiquer la version de son projet dans le bitstream vivado ?"},"content":{"rendered":"<p>En r\u00e8gle g\u00e9n\u00e9rale on aime bien avoir la version du firmware g\u00e9n\u00e9r\u00e9e sur lequel tourne notre FPGA. Cependant, pour int\u00e9grer une date de compile, une version de logiciel ou autre dans un bitstream, cela ne se fait pas tr\u00e8s simplement.<\/p>\n<p>L&rsquo;exemple ici est certainement <em>quick&#038;dirty<\/em>, mais c&rsquo;est une solution possible pour r\u00e9soudre ce probl\u00e8me. Le syst\u00e8me est con\u00e7u via le \u00abblocs designer\u00bb de vivado et contient un microblaze.<\/p>\n<p>Pour pouvoir ajouter des \u00abregistres\u00bb sp\u00e9cifiques sans avoir \u00e0 coder en HDL on int\u00e9grera un bloc de ROM nomm\u00e9 \u00abDistributed Memory Generator\u00bb. Pour int\u00e9grer ce bloc dans l&rsquo;espace m\u00e9moire du Microblaze on ajoutera un contr\u00f4leur de ram AXI comme le montre la saisie d&rsquo;\u00e9cran ci-dessous:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.fabienm.eu\/wordpress\/wp-content\/uploads\/2017\/03\/vivado_axi_rom_version-1024x255.png\" alt=\"\" width=\"640\" height=\"159\" class=\"aligncenter size-large wp-image-1012\" srcset=\"http:\/\/www.fabienm.eu\/wordpress\/wp-content\/uploads\/2017\/03\/vivado_axi_rom_version-1024x255.png 1024w, http:\/\/www.fabienm.eu\/wordpress\/wp-content\/uploads\/2017\/03\/vivado_axi_rom_version-300x75.png 300w, http:\/\/www.fabienm.eu\/wordpress\/wp-content\/uploads\/2017\/03\/vivado_axi_rom_version-768x191.png 768w, http:\/\/www.fabienm.eu\/wordpress\/wp-content\/uploads\/2017\/03\/vivado_axi_rom_version.png 1556w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/p>\n<p>Ce bloc peut \u00eatre configur\u00e9 via un fichier texte avec l&rsquo;extension \u00ab.coe\u00bb qui contiendra les valeurs. <\/p>\n<pre><code>\r\nmemory_initialization_radix=10;\r\nmemory_initialization_vector=1562 1490616824 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;\r\n<\/code><\/pre>\n<p>La variable <em>memory_initialization<\/em> indique la base (ici du d\u00e9cimal) des valeurs donn\u00e9es dans le vecteur <em>memory_initialization_vector<\/em>. Dans cet exemple, trois valeurs sont donn\u00e9es : la p\u00e9riode de l&rsquo;horloge du contr\u00f4leur de DDR, la date en secondes unix et la version.<\/p>\n<p>Plut\u00f4t que d&rsquo;avoir \u00e0 modifier notre fichier *.coe \u00e0 chaque synth\u00e8se, nous allons \u00e9crire un <a href=\"http:\/\/www.xilinx.com\/support\/documentation\/sw_manuals\/xilinx2012_3\/ug894-vivado-tcl-scripting.pdf\">script tcl<\/a> qui sera appel\u00e9 automatiquement par vivado \u00e0 chaque synth\u00e8se\/placement-routage. Le TCL est un langage de script que beaucoup de logiciels d&rsquo;\u00e9lectronique sont capable d&rsquo;\u00e9xecuter, c&rsquo;est le cas de vivado (tcl version 8.5).<\/p>\n<p>Le r\u00e9pertoire du projet est donn\u00e9 par la commande tcl :<\/p>\n<pre><source>\r\nset current_project_dir [get_property DIRECTORY [current_project]]\r\n<\/source><\/pre>\n<p>On peut l&rsquo;afficher au besoin dans la console \u00abMessages\u00bb de vivado avec puts :<\/p>\n<pre><source>\r\nputs $current_project_dir\r\n<\/source><\/pre>\n<h3>p\u00e9riode du contr\u00f4leur de DDR<\/h3>\n<p>L&rsquo;id\u00e9e ici est d&rsquo;aller chercher l&rsquo;information dans le fichier datasheet.txt g\u00e9n\u00e9r\u00e9 par le fucking <a href=\"https:\/\/www.xilinx.com\/products\/intellectual-property\/mig.html\">MIG<\/a>. La m\u00e9thode Quick&#038;Dirty pour r\u00e9cup\u00e9rer l&rsquo;info dans le fichier est de d\u00e9couper le texte \u00e0 coup de <a href=\"http:\/\/wiki.tcl.tk\/1499\">split<\/a> et de <a href=\"http:\/\/www.tcl.tk\/man\/tcl8.5\/TclCmd\/lindex.htm\">lindex<\/a> pour se focaliser sur la \u00abDesign Clock Frequency\u00bb.<\/p>\n<pre>\r\n...\r\n\/*******************************************************\/\r\n\/*                  Controller 0                       *\/\r\n\/*******************************************************\/\r\nController Options :\r\n   Memory                        : DDR3_SDRAM\r\n   Interface                     : AXI\r\n   Design Clock Frequency        : 1562 ps (  0.00 MHz)\r\n   Phy to Controller Clock Ratio : 4:1\r\n   Input Clock Period            : 5077 ps\r\n   CLKFBOUT_MULT (PLL)           : 13\r\n   DIVCLK_DIVIDE (PLL)           : 2\r\n   VCC_AUX IO                    : 1.8V\r\n   Memory Type                   : Components\r\n   Memory Part                   : MT41K1G8SN-125\r\n   Equivalent Part(s)            : --\r\n   Data Width                    : 8\r\n   ECC                           : Disabled\r\n   Data Mask                     : enabled\r\n   ORDERING                      : Normal\r\n...\r\n<\/pre>\n<p>La p\u00e9riode est ainsi stock\u00e9e dans la variable <em>$period<\/em> :<\/p>\n<pre><source>\r\n# Get DDR period\r\nset fp [open \"$current_project_dir\/..\/..\/..\/projet.srcs\/sources_1\/bd\/ {...} \/datasheet.txt\"]\r\nset filedata [read $fp]\r\nset data [split $filedata \"\\n\"]\r\nforeach line $data {\r\n\tif {[regexp {Design} $line]} {\r\n\t\tset period [expr [lindex [split [lindex [split $line \":\"] 1] \"ps\"] 0]]\r\n\t} \r\n}\r\n<\/source><\/pre>\n<h3>version<\/h3>\n<p>Pour la version c&rsquo;est \u00e0 nous de d\u00e9finir un \u00abgeneric\u00bb dans le projet avec le nom que nous voulons (par exemple ProjectVersion). Ce generic se d\u00e9finit dans le menu setting du projet, pour cette exemple il sera d\u00e9fini \u00e0 &lsquo;1&rsquo;, quelle originalit\u00e9 !<\/p>\n<p>Ce generic se retrouve ensuite dans le fichier xml du projet au format *.xpr. De la m\u00eame mani\u00e8re que pour la period du contr\u00f4leur de DDR, nous allons lire ce fichier au moyen d&rsquo;une savante boucle de d\u00e9coupage split et lindex:<\/p>\n<pre><source>\r\nset fp [open \"$current_project_dir\/..\/..\/project.xpr\"]\r\nset filedata [read $fp]\r\nset data [split $filedata \"\\n\"]\r\nforeach line $data {\r\n\tif {[regexp {ProjectVersion} $line]} {\r\n\t\tset ProjectVersion [lindex [split [string trim $line] \"\\\"\"] 3]\r\n\t} \r\n}\r\n<\/source><\/pre>\n<h3>date<\/h3>\n<p>Pour la date c&rsquo;est beaucoup plus simple puisqu&rsquo;il existe une commande tcl (>=8.5) qui nous donne les \u00abseconds unix\u00bb : <em>clock seconds<\/em>.<\/p>\n<pre><source>\r\nset thetime [clock seconds]\r\n<\/source><\/pre>\n<h3>Enregistrement du fichier coe<\/h3>\n<p>Il suffit pour cela d&rsquo;ouvrir en \u00e9criture le pathname que nous d\u00e9sinons \u00e9crire puis ajouter les valeurs avec puts :<\/p>\n<pre><source>\r\n# Write coe file for rom\r\nset wfp [open \"$current_project_dir\/..\/..\/..\/..\/rom_version.coe\" w]\r\nputs $wfp \"memory_initialization_radix=10;\"\r\nputs $wfp \"memory_initialization_vector=$period $thetime $ProjectVersion 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;\"\r\n<\/source><\/pre>\n<h3>Ajout du crochet (hook)<\/h3>\n<p>Pour que notre script tcl soit appel\u00e9 automatiquement par vivado il faut le d\u00e9finir comme un \u00abhook\u00bb de pre-synth\u00e8se. Pour cela il faut se rendre dans le menu de configuration de la synth\u00e8se:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.fabienm.eu\/wordpress\/wp-content\/uploads\/2017\/03\/vivado_synthesis_settings.png\" alt=\"\" width=\"207\" height=\"55\" class=\"aligncenter size-full wp-image-1019\" \/><\/p>\n<p>Puis s\u00e9lectionner notre script name.tcl dans l&rsquo;option tcl.pre (pour pre-synth\u00e8se).<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.fabienm.eu\/wordpress\/wp-content\/uploads\/2017\/03\/vivado_pre_commit_hook.png\" alt=\"\" width=\"941\" height=\"119\" class=\"aligncenter size-full wp-image-1021\" srcset=\"http:\/\/www.fabienm.eu\/wordpress\/wp-content\/uploads\/2017\/03\/vivado_pre_commit_hook.png 941w, http:\/\/www.fabienm.eu\/wordpress\/wp-content\/uploads\/2017\/03\/vivado_pre_commit_hook-300x38.png 300w, http:\/\/www.fabienm.eu\/wordpress\/wp-content\/uploads\/2017\/03\/vivado_pre_commit_hook-768x97.png 768w, http:\/\/www.fabienm.eu\/wordpress\/wp-content\/uploads\/2017\/03\/vivado_pre_commit_hook-940x119.png 940w\" sizes=\"auto, (max-width: 941px) 100vw, 941px\" \/><\/p>\n<p>Le script sera ex\u00e9cut\u00e9 dans le r\u00e9pertoire :<source><pre>\r\nproject\/project.runs\/run_name\/\r\n<\/pre>\n<p><\/source><\/p>\n<p>Il suffit maintenant de lancer la synth\u00e8se pour que notre \u00abhook\u00bb soit lanc\u00e9 avant la synth\u00e8se et remplisse correctement la rom de param\u00e8tres de notre design.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>En r\u00e8gle g\u00e9n\u00e9rale on aime bien avoir la version du firmware g\u00e9n\u00e9r\u00e9e sur lequel tourne notre FPGA. Cependant, pour int\u00e9grer une date de compile, une version de logiciel ou autre dans un bitstream, cela ne se fait pas tr\u00e8s simplement. &hellip; <a href=\"http:\/\/www.fabienm.eu\/wordpress\/2017\/03\/27\/comment-indiquer-la-version-de-son-projet-dans-le-bitstream-vivado\/\">Continuer la lecture <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10],"tags":[57,112,170,168],"class_list":["post-1007","post","type-post","status-publish","format-standard","hentry","category-informatique","tag-armadeus","tag-fpga","tag-tcl","tag-vivado"],"_links":{"self":[{"href":"http:\/\/www.fabienm.eu\/wordpress\/wp-json\/wp\/v2\/posts\/1007","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.fabienm.eu\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.fabienm.eu\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.fabienm.eu\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.fabienm.eu\/wordpress\/wp-json\/wp\/v2\/comments?post=1007"}],"version-history":[{"count":23,"href":"http:\/\/www.fabienm.eu\/wordpress\/wp-json\/wp\/v2\/posts\/1007\/revisions"}],"predecessor-version":[{"id":1033,"href":"http:\/\/www.fabienm.eu\/wordpress\/wp-json\/wp\/v2\/posts\/1007\/revisions\/1033"}],"wp:attachment":[{"href":"http:\/\/www.fabienm.eu\/wordpress\/wp-json\/wp\/v2\/media?parent=1007"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.fabienm.eu\/wordpress\/wp-json\/wp\/v2\/categories?post=1007"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.fabienm.eu\/wordpress\/wp-json\/wp\/v2\/tags?post=1007"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}