{"id":1670,"date":"2021-04-29T19:34:53","date_gmt":"2021-04-29T18:34:53","guid":{"rendered":"http:\/\/www.fabienm.eu\/flf\/?p=1670"},"modified":"2021-04-29T19:34:53","modified_gmt":"2021-04-29T18:34:53","slug":"compteur-de-build-en-chisel","status":"publish","type":"post","link":"http:\/\/www.fabienm.eu\/flf\/compteur-de-build-en-chisel\/","title":{"rendered":"Compteur de \u00abbuild\u00bb en Chisel"},"content":{"rendered":"\n<p>Ais-je bien t\u00e9l\u00e9charg\u00e9 la derni\u00e8re version de mon <strong>gateware<\/strong> dans ce montage ?<\/p>\n\n\n\n<p>C&rsquo;est un probl\u00e8me classique quand on fait de l&#8217;embarqu\u00e9, entre l&rsquo;\u00e9diteur de code, la g\u00e9n\u00e9ration du code bas niveau (Verilog dans le cas de Chisel) le logiciel de synth\u00e8se\/placement-routage et le t\u00e9l\u00e9chargement du <strong>bitstream<\/strong>, il y a plein de fa\u00e7on de se tromper de version du logiciel s&rsquo;ex\u00e9cutant r\u00e9ellement dans le montage. Et l&rsquo;on peu passer des heures \u00e0 chercher un bug dans son syst\u00e8me en modifiant des lignes de code alors que le probl\u00e8me vient d&rsquo;une m\u00eame (vieille) version t\u00e9l\u00e9charg\u00e9e \u00e9ternellement.<\/p>\n\n\n\n<p>Pour s&rsquo;assurer que le gateware qui se trouve dans le <strong>FPGA<\/strong> soit bien le dernier g\u00e9n\u00e9r\u00e9 il faut  trouver une mani\u00e8re d&rsquo;y enregistrer une valeur qui sera diff\u00e9rente \u00e0 chaque fois.<\/p>\n\n\n\n<p>On pourrait mettre une version \u00aben dur\u00bb dans nos sources, mais l&rsquo;exp\u00e9rience montre que l&rsquo;on oublie 4 fois sur 5 de l&rsquo;incr\u00e9menter avant de g\u00e9n\u00e9rer le fichier. Toute bonne d\u00e9veloppeuse et tout bon d\u00e9veloppeur versionne son projet avec un gestionnaire de version. On  pourrait  du coup mettre le num\u00e9ro de commit. Sauf que l&rsquo;on ne commit pas toujours la modification avant de la tester.<\/p>\n\n\n\n<p>Une autre astuce consiste \u00e0 mettre la date <a href=\"https:\/\/en.wikipedia.org\/wiki\/Unix_time\" data-type=\"URL\" data-id=\"https:\/\/en.wikipedia.org\/wiki\/Unix_time\"><strong>EPOCH<\/strong><\/a>. De cette mani\u00e8re nous avons la date et l&rsquo;heure pr\u00e9cise de la synth\u00e8se du gateware. Cette solution est int\u00e9ressante mais elle pose rapidement un probl\u00e8me d&rsquo;occupation du <strong>FPGA<\/strong>. En effet, le temps en secondes filant assez rapidement nous avons besoin de registres de 32 bits minimum voir m\u00eame 64bits. Ce qui est plut\u00f4t inutile pour compter les builds &#8230;<\/p>\n\n\n\n<p><strong>Compter les builds ?<\/strong><\/p>\n\n\n\n<p>La voila la solution toute simple, il suffit d&rsquo;enregistrer un compteur dans un fichier texte. \u00c0 chaque build, une fonction vient lire la valeur et l&rsquo;incr\u00e9mente. Pour rester \u00e0 jour il nous suffit ensuite de versionner ce fichier avec le reste du code. M\u00eame si le nombre de build est grand, on n&rsquo;aura rarement besoin d&rsquo;en faire plus de quelques millier, ce qui rentrera tr\u00e8s bien dans un registre de 16 bits voir moins. <\/p>\n\n\n\n<p>Voici comment faire en <strong>Scala<\/strong> avec <strong>Chisel<\/strong>.<\/p>\n\n\n\n<p>Dans un package avec les utilitaires \u00abpersonnel\u00bb :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package myutil\n<\/code><\/pre>\n\n\n\n<p>On importe les packages d&rsquo;entr\u00e9es sorties  pour lire\/\u00e9crire dans les fichiers textes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Pour fromFile()\nimport scala.io.Source\n\/\/ Pour PrintWriter()\nimport java.io._<\/code><\/pre>\n\n\n\n<p>Puis on cr\u00e9e une fonction de lecture \u00e9criture dans un objet personnel MyUtility :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n  def genCountVers(className: String = null): Option&#91;Int] = {\n    if(className == null){\n      return None\n    }\n    println(\"generate counter for class \" + className)\n    val filename = \"src\/main\/scala\/util\/gen_count_vers.txt\"\n    val versmap = scala.collection.mutable.Map&#91;String,Int]()\n\n    \/* read file to hashmap*\/\n    val fp = Source.fromFile(filename)\n    for(v &lt;- fp.getLines.map(_.split(\",\").map(_.trim))){\n      versmap(v(0)) = v(1).toInt\n    }\n    fp.close()\n  \n    \/* get and increment version *\/\n    val version = versmap.get(className)\n    if(version == None){\n      versmap(className) = 0\n    } else {\n      versmap(className) = version.get.toInt + 1\n    }\n\n    \/* write back file*\/\n    val fpw = new PrintWriter(new File(filename))\n    for ((hname, hvalue) &lt;- versmap) {\n      fpw.write(hname + \",\" + hvalue + \"\\n\")\n    }\n    fpw.close()\n\n    \/* return version *\/\n    version match {\n      case Some(s) =&gt; Some(s.toInt + 1)\n      case None =&gt; Some(0)\n    }\n  }<\/code><\/pre>\n\n\n\n<p>La fonction <code>genCountVers()<\/code> va ouvrir le fichier texte <code>gen_count_vers.txt<\/code>, qui est un \u00abCSV\u00bb compos\u00e9 du nom de classes et d&rsquo;un num\u00e9ro. Si le nom de la classe pass\u00e9 en param\u00e8tre n&rsquo;existe pas la fonction va l&rsquo;ajouter avec un compteur \u00e0 zero.<\/p>\n\n\n\n<p> Nous n&rsquo;avons plus qu&rsquo;a appeler la fonction genCounterVers() avec le nom de la classe (ou autre) de notre choix pour la fourrer dans un registre lisible via notre interface (spi, wisbone, i2c, jtag, &#8230;) directement sur le FPGA :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>val buildnum = MyUtility.genCounterVers(\"MyTopClasse\").get<\/code><\/pre>\n\n\n\n<pre id=\"block-98f1edec-b926-42a5-a84a-d51304489ddc\" class=\"wp-block-code\"><code><\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Ais-je bien t\u00e9l\u00e9charg\u00e9 la derni\u00e8re version de mon gateware dans ce montage ? C&rsquo;est un probl\u00e8me classique quand on fait de l&#8217;embarqu\u00e9, entre l&rsquo;\u00e9diteur de code, la g\u00e9n\u00e9ration du code bas niveau (Verilog dans le cas de Chisel) le logiciel de synth\u00e8se\/placement-routage et le t\u00e9l\u00e9chargement du bitstream, il y a plein de fa\u00e7on de se &hellip; <a href=\"http:\/\/www.fabienm.eu\/flf\/compteur-de-build-en-chisel\/\" class=\"more-link\">Continuer la lecture de <span class=\"screen-reader-text\">Compteur de \u00abbuild\u00bb en Chisel<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_uag_custom_page_level_css":"","footnotes":""},"categories":[2],"tags":[195,57,71,53],"class_list":["post-1670","post","type-post","status-publish","format-standard","hentry","category-chisel","tag-build","tag-chisel","tag-fpga","tag-truc"],"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false,"post-thumbnail":false},"uagb_author_info":{"display_name":"Fabien Marteau","author_link":"http:\/\/www.fabienm.eu\/flf\/author\/martoni\/"},"uagb_comment_info":0,"uagb_excerpt":"Ais-je bien t\u00e9l\u00e9charg\u00e9 la derni\u00e8re version de mon gateware dans ce montage ? C&rsquo;est un probl\u00e8me classique quand on fait de l&#8217;embarqu\u00e9, entre l&rsquo;\u00e9diteur de code, la g\u00e9n\u00e9ration du code bas niveau (Verilog dans le cas de Chisel) le logiciel de synth\u00e8se\/placement-routage et le t\u00e9l\u00e9chargement du bitstream, il y a plein de fa\u00e7on de se\u2026","_links":{"self":[{"href":"http:\/\/www.fabienm.eu\/flf\/wp-json\/wp\/v2\/posts\/1670","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.fabienm.eu\/flf\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.fabienm.eu\/flf\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.fabienm.eu\/flf\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.fabienm.eu\/flf\/wp-json\/wp\/v2\/comments?post=1670"}],"version-history":[{"count":12,"href":"http:\/\/www.fabienm.eu\/flf\/wp-json\/wp\/v2\/posts\/1670\/revisions"}],"predecessor-version":[{"id":1689,"href":"http:\/\/www.fabienm.eu\/flf\/wp-json\/wp\/v2\/posts\/1670\/revisions\/1689"}],"wp:attachment":[{"href":"http:\/\/www.fabienm.eu\/flf\/wp-json\/wp\/v2\/media?parent=1670"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.fabienm.eu\/flf\/wp-json\/wp\/v2\/categories?post=1670"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.fabienm.eu\/flf\/wp-json\/wp\/v2\/tags?post=1670"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}