{"id":683,"date":"2020-11-22T16:36:39","date_gmt":"2020-11-22T16:36:39","guid":{"rendered":"http:\/\/dsd.webs.upv.es\/?p=683"},"modified":"2021-05-12T07:27:46","modified_gmt":"2021-05-12T07:27:46","slug":"rcsg-y-cobertura-funcional-en-microprocesadores","status":"publish","type":"post","link":"https:\/\/dsd.webs.upv.es\/?p=683","title":{"rendered":"RCSG y cobertura funcional en microprocesadores"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">He creado esta entrada para que pensemos c\u00f3mo podemos utilizar RCSG y covergroups en la verificaci\u00f3n de un microprocesador.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Una forma que se me ocurre de hacerlo (y desde luego no es \u00fanica) es la que os voy a describir. Es el momento adecuado porque empezamos esta semana a conocer el c\u00f3digo m\u00e1quina de los diferentes tipos de instrucciones del RISC-V que tenemos entre manos.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">RCSG<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Lo primero que pens\u00e9 fue que la mejor manera de aleatorizar las instrucciones que realiza un microprocesador es aleatorizar el contenido txt que introducimos en la memoria ROM.  Pero luego pens\u00e9 que quiz\u00e1 fuera interesante modelizar la memoria ROM con dos estilos: Estilo sintetizable directo y estilo random. <\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>El primero utilizar\u00eda el cl\u00e1sico txt para inicializar el contenido y deber\u00eda ser sintetizable por quartus sin problemas. <\/li><li>El segundo generar\u00eda cada vez que el \u00abaddress\u00bb cambiara un contenido gobernado por una clase RCSG, intentando claro est\u00e1 que si volviera a repetirse alg\u00fan \u00abaddress\u00bb el contenido aleatorio se repitiera.<\/li><\/ul>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:verilog decode:true \">module rom_aleatoria (address,dout);\nparameter d_width = 32;\nparameter mem_depth = 1024;\nlocalparam a_width=$clog2(mem_depth);\ninput [a_width-1:0] address;\noutput logic [d_width-1:0] dout;\n \nlogic [d_width-1:0] mem[mem_depth-1:0] ; \n \n`ifndef debug_aleatorio \n \ninitial\n    $readmemh(\"contenido_fijo.dat\", mem); \nassign dout = mem[address];\n\n`else \n\nlogic [31:0] tipos_paquete[logic [9:0] ]; \/\/ tipo de paquete es 16 bits\n\nlogic [31:0] temp;\nalways @(address)\nif (!tipos_paquete.exists(address))\n  begin\n    rom_aleatoria_tb.m1.get(temp);\n    tipos_paquete[address]=temp;\t\n    dout=tipos_paquete[address];\n  end\nelse\n   begin\n    rom_aleatoria_tb.m1.get(temp);\n    dout=tipos_paquete[address];\n   end\n\n`endif\n\nendmodule<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Puede verse estos dos estilos separados mediante una compilaci\u00f3n condicional en la que elijamos o el comportamiento directo sintetizable o el comportamiento aleatorio.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p class=\"wp-block-paragraph\">Vamos a centrarnos en el comportamiento aleatorio (desde la l\u00ednea 16 hasta la 26) que tiene m\u00e1s elementos nuevos.<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Cada vez que always se reanuda y ejecuta por un cambio de \u00abaddress\u00bb, obtenemos desde un \u00abmailbox\u00bb denominado <strong>m1<\/strong>  un valor \u00abrandom\u00bb<ul><li>Para ello una cierta infraestructura es necesaria, como por ejemplo la declaraci\u00f3n de un mailbox que maneje mensajes de 32 bits, lo cual haremos desde el top de todo nuestro banco de pruebas y la escritura del mailbox  que haremos desde  la construcci\u00f3n \u00abprogram\u00bb donde centralizaremos todos los elementos de test. Mas adelante veremos esas sintaxis. Lo que si que adelanto es que evidentemente el valor \u00abrandom\u00bb lo conseguir\u00e9 por el uso del m\u00e9todo randomize que ya todos conoc\u00e9is.<\/li><li>Otra cosa que necesitamos es un peque\u00f1o diccionario (implementado con un array asociativo) que asocie una direcci\u00f3n con un valor aleatorio, de forma que si el microprocesador transitara de nuevo por la misma direcci\u00f3n, detectemos que ese \u00abaddress\u00bb ya ha sido utilizado y reusemos el valor aleatorio generado la primera vez que ese address se utiliz\u00f3 (el valor procedente del mailbox se lee para vaciarlo, aunque no se usa).<\/li><\/ul><\/li><\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Veamos como ser\u00eda la clase donde generamos el valor aleatorio.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:verilog decode:true \" title=\"Clase RCSG\">class RCSG_RISCV;\n  rand logic [31:0] valor;\n  constraint R_format    {valor[6:0] == 7'b0110011;}\n  constraint R_format_a  {(valor[6:0] == 7'b0110011 &amp;&amp; valor[14:12]!=3'b000 &amp;&amp; valor[14:12]!=3'b101) -&gt; valor[31:25]==7'b0000000 ;}\n  constraint R_format_b  {(valor[6:0] == 7'b0110011 &amp;&amp; (valor[14:12]==3'b000) || valor[14:12]==3'b101) -&gt; valor[31:25]==7'b0000000 || valor[31:25]==7'b0100000 ;}\nendclass<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">He creado unos \u00abconstraints\u00bb  para conseguir unas instrucciones de tipo R_format. la primera de esas constraints elige un tipo de instrucciones y deber\u00e1 habilitarse o deshabilitarse seg\u00fan convenga, mientras que las dos siguientes \u00abconstraints\u00bb son derivadas de la anterior y pueden estar siempre habilitadas.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ya solo nos quedar\u00eda ver c\u00f3mo usamos dicha clase. Este uso lo vamos a centralizar en el test (realizado con un program).<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:verilog decode:true \">program  estimulos (if_rom.testar testar_ports, if_rom.monitorizar monitorizar_ports);\n\n utilidades_verificacion::RCSG_RISCV generar_instrucciones;\n utilidades_verificacion::covergroups_RISCV monitorizar_instrucciones;\n\nlogic [31:0] instruccion_random;\n\n  initial \n    begin\n      generar_instrucciones=new;\n      monitorizar_instrucciones=new(monitorizar_ports);\n\n      # 50;\n\n      $display(\"probando r_format\" );\n      generar_instrucciones.R_format.constraint_mode(1);\n      prueba_random_r_format();\n      $stop;\n      $writememh(\"salida_random.txt\", rom_aleatoria_tb.rom_aleatoria_dut.duv.tipos_paquete);      \n      $finish;\n\n  end\n\ntask prueba_random_r_format;\n  begin\n      generar_instrucciones.randomize();      \n      rom_aleatoria_tb.m1.put(generar_instrucciones.valor);\n      testar_ports.address='0; \n      #0 monitorizar_instrucciones.instrucciones.sample();  \n      while ( monitorizar_instrucciones.instrucciones.rformat.get_coverage()&lt;100)\n\tbegin\n\t   # 100 ;\n\t   generar_instrucciones.randomize();      \n     \t   rom_aleatoria_tb.m1.put(generar_instrucciones.valor);\n\t   testar_ports.address= testar_ports.address +1;\n           #0 monitorizar_instrucciones.instrucciones.sample();\n        end\n  end\nendtask\n\nendprogram<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"> En este c\u00f3digo se puede observar la generaci\u00f3n del valor aleatorio y su escritura en el \u00abmailbox\u00bb <strong>m1<\/strong>, cada vez que vamos a generar un nuevo address. Previamente hemos hecho la declaraci\u00f3n  (l\u00ednea 3) y la creaci\u00f3n (l\u00ednea 10)  del objeto que hab\u00edamos visto su definici\u00f3n en el c\u00f3digo Clase RCSG.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En cuanto a la l\u00ednea 19, podemos ver como escribir los contenidos aleatorios en un fichero txt para su posterior uso.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Cobertura funcional<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Volvamos al c\u00f3digo anterior y ya se vislumbra la declaraci\u00f3n (l\u00ednea 4) y creaci\u00f3n (l\u00ednea 11) del covergroup necesario para monitorizar las instrucciones. Solo nos faltar\u00eda visualizar la definici\u00f3n del covergroup que tenemos en la siguiente secci\u00f3n de c\u00f3digo:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:verilog decode:true \">class covergroups_RISCV;\n\nvirtual if_rom.monitorizar monitor_port;\n\ncovergroup instrucciones ;\n\n  rformat : coverpoint ({monitor_port.dato[30],monitor_port.dato[14:12]})  iff (monitor_port.dato[6:0]==7'b0110011&amp;&amp;monitor_port.dato[31]==1'b0&amp;&amp;monitor_port.dato[29:25]==5'b0000)\n  {\n      bins add ={0};\n      bins sub={8};      \n      bins sll={1};\n      bins slt={2};\n      bins sltu={3};\n      bins ixor={4};\n      bins slr={5};\n      bins sra={13};\n      bins ior={6};\n      bins iand={7};\n      illegal_bins imposibles_rformat={9,10,11,12,14,15}; \n  } \nendgroup\nfunction new(virtual if_rom.monitorizar mpuertos);\n\tmonitor_port=mpuertos;\n\tinstrucciones=new;\nendfunction \nendclass\t<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Comentemos algunos detalles:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>El <strong>covergroup <\/strong>como era de esperar es inmediato y requiere del uso del m\u00e9todo \u00absample\u00bb para determinar el momento de muestreo. Ver lineas 29 y 36 del c\u00f3digo del <strong>program<\/strong> en donde utilizamos dicho m\u00e9todo de muestreo.<\/li><li>He puesto al <strong>coverpoint <\/strong>de una condici\u00f3n de enable (<strong>iff<\/strong>) que me permita habilitar \u00fanicamente el cubrimiento de esas combinaciones de c\u00f3digo cuando estemos realmente en una instrucci\u00f3n r_format.<\/li><li>Recurro a un interface virtual para poder obtener la monitorizaci\u00f3n del puerto de salida de la ROM. Ya lo hab\u00edamos hecho en otros ejemplos y he recurrido a una estructura muy parecida a la utilizada en el ejemplo final de la verificaci\u00f3n del radicador<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Estructura completa<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Ya solo nos quedan los detalles. El primero es que las dos clases utilizadas las he puesto en un paquete con el nombre de <strong>utilidades_verificacion<\/strong>. <\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:verilog decode:true \">package utilidades_verificacion;\n\ntypedef mailbox #(logic [31:0]) instruction_box;\n\nclass RCSG_RISCV;\n....\nendclass\nclass covergroups_RISCV;\n...\nendclass\n\nendpackage<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Para la monitorizaci\u00f3n de los puertos de salida ha sido esencial la definici\u00f3n de un interfaz que todo lo una. Un interfaz con los t\u00edpicos tres modos que ya hemos utilizado en otros ejemplos y en el que destaca la ausencia de elementos de sincronizaci\u00f3n (<strong>clocking blocks<\/strong>) . Eso puede suponer un problema que puede ser subsanado con t\u00e9cnicas manuales de sincronizaci\u00f3n como es la utilizaci\u00f3n del <strong>cero delay<\/strong> visible en las l\u00edneas 29 y 36 del <strong>program<\/strong>. Esta t\u00e9cnica me garantiza que cuando monitorizo el puerto de salida en un instante en que ese puerto debe cambiar, el valor que monitorizo ser\u00e1 el nuevo generado puesto que pospongo la lectura de muestreo al final de ese instante.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:verilog decode:true \">interface if_rom;\n\nlogic [9:0] address;\nlogic [31:0] dato;\n\nmodport monitorizar\n(input address,\ninput dato);\n\nmodport testar\n(output address,\ninput dato);\n\nmodport duv\n(input address,\noutput dato);\nendinterface<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Por supuesto la utilizaci\u00f3n del interfaz me obliga a encapsular el duv en un livel jer\u00e1rquico superior que utilice dicho interfaz<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:verilog decode:true \">module top_duv( if_rom.duv bus);\n\nrom_aleatoria #(.d_width(32), .mem_depth(1024)) duv\n(.address(bus.address),\n.dout(bus.dato));\n\nendmodule<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Ya solo nos queda el banco de pruebas (top de nuestra jerarqu\u00eda) en donde destacar\u00e1 la declaraci\u00f3n y construcci\u00f3n del mailbox que vamos a utilizar para intercomunicar los procesos de los est\u00edmulos (program) con los del duv (modelo de la memoria aleatorizada)<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:verilog decode:true \">module rom_aleatoria_tb ();\n\n  \/\/ Parameters\n  localparam  d_width = 32;\n  localparam  mem_depth = 1024;\n  localparam a_width=$clog2(mem_depth);\n  \/\/ Ports\n  reg [a_width-1:0] address;\n  reg clk;\n  logic [d_width-1:0] dato;\n\nutilidades_verificacion::instruction_box m1=new();\n\nif_rom interfaz_rom ();\n\ntop_duv    rom_aleatoria_dut (.bus(interfaz_rom) );\n\nestimulos  rom_aleatoria_estimulos (.testar_ports(interfaz_rom), .monitorizar_ports(interfaz_rom));\n\n\nendmodule<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Y para terminar un \u00faltimo detalle. Este comportamiento aleatorio de la ROM solo ser\u00e1 efectivo si cuando compile con vlog defina la variable \u00abdebug_aleatorio\u00bb.  Si hago una compilaci\u00f3n con las opciones por defecto actuar\u00e1 la ROM sintetizable y cargada desde un txt y por tanto sin ning\u00fan tipo de aleatorizaci\u00f3n. La forma de compilar con esa definici\u00f3n de variable es:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">vlog +define+debug_aleatorio rom_aleatoria.sv<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Veamos con el siguiente v\u00eddeo el comportamiento de esta simulaci\u00f3n:<\/p>\n\n\n\n<iframe loading=\"lazy\" allowfullscreen=\"\" src=\"https:\/\/media.upv.es\/player\/embed.html?id=e97971d0-2d86-11eb-9cbc-4baa4998ef22\" style=\"border:0px #FFFFFF none;\" name=\"Paella Player\" scrolling=\"no\" frameborder=\"0\" marginheight=\"0px\" marginwidth=\"0px\" width=\"640\" height=\"360\"> <\/iframe>\n\n\n\n<p class=\"wp-block-paragraph\">Para que pod\u00e1is probar el proyecto adjunto el mismo en le siguiente laboratorio virtual:<\/p>\n\n\n\n[iframe width=\u00bb100%\u00bb height=\u00bb480&#8243; src=\u00bbhttps:\/\/www.edaplayground.com\/x\/jztC\u00bb]\n","protected":false},"excerpt":{"rendered":"<p>He creado esta entrada para que pensemos c\u00f3mo podemos utilizar RCSG y covergroups en la verificaci\u00f3n de un microprocesador. Una forma que se me ocurre de hacerlo (y desde luego no es \u00fanica) es la que os voy a describir. Es el momento adecuado porque empezamos esta semana a conocer el c\u00f3digo m\u00e1quina de los diferentes tipos de instrucciones del RISC-V que tenemos entre manos. RCSG Lo primero que pens\u00e9 fue que la mejor manera de aleatorizar las instrucciones que realiza un microprocesador es aleatorizar el contenido txt que introducimos en la memoria ROM. Pero luego pens\u00e9 que quiz\u00e1 fuera interesante modelizar la memoria ROM con dos estilos: Estilo sintetizable directo y estilo random. El primero utilizar\u00eda el cl\u00e1sico txt para inicializar el contenido y deber\u00eda ser sintetizable por quartus sin problemas. El segundo generar\u00eda cada vez que el \u00abaddress\u00bb cambiara un contenido gobernado por una clase RCSG, intentando claro est\u00e1 que si volviera a repetirse alg\u00fan \u00abaddress\u00bb el contenido aleatorio se repitiera. Puede verse estos dos estilos separados mediante una compilaci\u00f3n condicional en la que elijamos o el comportamiento directo sintetizable o el comportamiento aleatorio.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_crdt_document":"","ub_ctt_via":"","footnotes":""},"categories":[5,36],"tags":[33,31,34,32,30],"class_list":["post-683","post","type-post","status-publish","format-standard","hentry","category-verificacion","category-verificacion-funcional-verificacion","tag-arrays-asociativos","tag-cobertura-funcional","tag-mailbox","tag-microprocesadores","tag-rcsg"],"featured_image_src":null,"author_info":{"display_name":"ralfgad","author_link":"https:\/\/dsd.webs.upv.es\/?author=2"},"_links":{"self":[{"href":"https:\/\/dsd.webs.upv.es\/index.php?rest_route=\/wp\/v2\/posts\/683","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dsd.webs.upv.es\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dsd.webs.upv.es\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dsd.webs.upv.es\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/dsd.webs.upv.es\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=683"}],"version-history":[{"count":19,"href":"https:\/\/dsd.webs.upv.es\/index.php?rest_route=\/wp\/v2\/posts\/683\/revisions"}],"predecessor-version":[{"id":779,"href":"https:\/\/dsd.webs.upv.es\/index.php?rest_route=\/wp\/v2\/posts\/683\/revisions\/779"}],"wp:attachment":[{"href":"https:\/\/dsd.webs.upv.es\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=683"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dsd.webs.upv.es\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=683"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dsd.webs.upv.es\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=683"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}