{"id":1757,"date":"2025-08-06T08:02:56","date_gmt":"2025-08-06T08:02:56","guid":{"rendered":"https:\/\/dsd.webs.upv.es\/?page_id=1757"},"modified":"2025-08-06T17:50:36","modified_gmt":"2025-08-06T17:50:36","slug":"concurrencia-en-systemverilog","status":"publish","type":"page","link":"https:\/\/dsd.webs.upv.es\/?page_id=1757","title":{"rendered":"Concurrencia en Systemverilog"},"content":{"rendered":"\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Modelo de Programaci\u00f3n Concurrente en SystemVerilog<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">SystemVerilog introduce nuevas herramientas avanzadas para manejar la concurrencia, esenciales para la verificaci\u00f3n de dise\u00f1os complejos. Ni que decir tiene que hereda toda la concurrencia que hemos visto en Veirlog; pero hace unas incorporaciones y mejoras interesantes-  <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Lanzar procesos paralelos:<\/strong> <code>fork\/join<\/code> <\/li>\n\n\n\n<li><strong>Aislamiento de variables:<\/strong> Variables locales a los threads.<\/li>\n\n\n\n<li><strong>Intercomunicaci\u00f3n:<\/strong> Mailboxes y variables compartidas.<\/li>\n\n\n\n<li><strong>Arbitraje y exclusi\u00f3n mutua:<\/strong> Sem\u00e1foros.<\/li>\n\n\n\n<li><strong>Sincronizaci\u00f3n:<\/strong> Eventos.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">Construcci\u00f3n <code>fork<\/code>\/<code>join<\/code><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">SystemVerilog mejora el <code>fork\/join<\/code> de Verilog con modificadores que controlan cu\u00e1ndo el proceso \u00abpadre\u00bb contin\u00faa su ejecuci\u00f3n.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>join<\/code>: El padre espera a que <strong>todos<\/strong> los procesos hijos terminen. (Comportamiento por defecto) .<\/li>\n\n\n\n<li><code>join_any<\/code>: El padre espera a que <strong>el primer<\/strong> proceso hijo termine.<\/li>\n\n\n\n<li><code>join_none<\/code>: El padre <strong>no espera<\/strong> y contin\u00faa su ejecuci\u00f3n en paralelo con los hijos.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Ejemplo de Control del <code>join<\/code>:<\/strong><\/p>\n\n\n<pre class=\"brush: systemverilog; title: ; notranslate\" title=\"\">\ninitial \nbegin\n fork \n    begin\n      fork\n        ##1 mi_variable_any=2&#039;d0; \/\/ child_1 (termina en t=1)\n        ##2 mi_variable_any=2&#039;d1; \/\/ child_2 (termina en t=2)\n        ##3 mi_variable_any=2&#039;d2; \/\/ child_3 (termina en t=3)\n      join_any \n      \/\/ El padre se reanuda en t=1 con join_any\n      ##3 mi_variable_any=2&#039;d3;\n      \/\/ mi_variable pasa a 3  en t=4 con join_any\n      ##2 ;\n    end\n    begin\n      fork\n        ##1 mi_variable_none=2&#039;d0; \/\/ child_1 (termina en t=1)\n        ##2 mi_variable_none=2&#039;d1; \/\/ child_2 (termina en t=2)\n        ##3 mi_variable_none=2&#039;d2; \/\/ child_3 (termina en t=3)\n      join_none \n      \/\/ El padre se reanuda en t=0 con join_none\n      ##3 mi_variable_none=2&#039;d3;\n      \/\/ mi_variable pasa a 3  en t=3 con join_none\n      ##2 ;\n    end\n    begin\n      fork\n        ##1 mi_variable_all=2&#039;d0; \/\/ child_1 (termina en t=1)\n        ##2 mi_variable_all=2&#039;d1; \/\/ child_2 (termina en t=2)\n        ##3 mi_variable_all=2&#039;d2; \/\/ child_3 (termina en t=3)\n      join\n      \/\/ El padre se reanuda en t=3 con join\n      ##3 mi_variable_all=2&#039;d3;\n      \/\/ mi_variable pasa a 3  en t=6 con join\n      ##2 ;\n    end  \n join\n $finish;\nend\n<\/pre>\n\n\n<style>\n       .errordiv { padding:10px; margin:10px; border: 1px solid #555555;color: #000000;background-color: #f8f8f8; width:500px; }#advanced_iframe {visibility:visible;opacity:1;vertical-align:top;}.ai-info-bottom-iframe { position: fixed; z-index: 10000; bottom:0; left: 0; margin: 0px; text-align: center; width: 100%; background-color: #ff9999; padding-left: 5px;padding-bottom: 5px; border-top: 1px solid #aaa } a.ai-bold {font-weight: bold;}#ai-layer-div-advanced_iframe p {height:100%;margin:0;padding:0}<\/style><script type=\"text\/javascript\">var ai_iframe_width_advanced_iframe = 0;var ai_iframe_height_advanced_iframe = 0;function aiReceiveMessageadvanced_iframe(event) {  aiProcessMessage(event,\"advanced_iframe\", \"true\",\"\",\"false\",\"false\");}if (window.addEventListener) {  window.addEventListener(\"message\", aiReceiveMessageadvanced_iframe);} else if (el.attachEvent)  {  el.attachEvent(\"message\", aiReceiveMessageadvanced_iframe);}var aiOnloadScrollTop=\"true\";var aiShowDebug=false;\n\t\tif (typeof aiReadyCallbacks === 'undefined') {\n\t\t\tvar aiReadyCallbacks = [];\n\t\t} else if (!(aiReadyCallbacks instanceof Array)) {\n\t\t\tvar aiReadyCallbacks = [];\n\t\t}    function aiShowIframeId(id_iframe) { jQuery(\"#\"+id_iframe).css(\"visibility\", \"visible\");    }    function aiResizeIframeHeight(height) { aiResizeIframeHeight(height,advanced_iframe); }    function aiResizeIframeHeightId(height,width,id) {aiResizeIframeHeightById(id,height);}<\/script><iframe id=\"advanced_iframe\"  name=\"advanced_iframe\"  src=\"https:\/\/drom.io\/vcd\/?github=ralfgad\/simulaciones_vcd\/main\/fork_join_1.vcd\"  width=\"100%\"  height=\"250\"  frameborder=\"0\"  border=\"0\"  allowtransparency=\"true\"  loading=\"lazy\"  style=\";border-width: 0px;;border: none;;width:100%;;height:250px;\" ><\/iframe><script type=\"text\/javascript\">var ifrm_advanced_iframe = document.getElementById(\"advanced_iframe\");var hiddenTabsDoneadvanced_iframe = false;\nfunction resizeCallbackadvanced_iframe() {}<\/script><script type=\"text\/javascript\"><\/script><p style=\"display:block !important; visibility:visible !important;margin: -18px 14px 0 0;padding-left: 3px;padding-top:3px;background: white; overflow: hidden; position: relative; line-height:15px;width: fit-content;\"><small style=\"display:block !important;visibility:visible !important\">powered by Advanced iFrame<\/small><\/p>\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.edaplayground.com\/x\/PXPS\" target=\"_blank\" rel=\"noreferrer noopener\"><img loading=\"lazy\" decoding=\"async\" width=\"295\" height=\"71\" src=\"https:\/\/dsd.webs.upv.es\/wp-content\/uploads\/2023\/09\/image-3.png\" alt=\"\" class=\"wp-image-1504\"\/><\/a><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Sem\u00e1foros<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Un sem\u00e1foro es un mecanismo de arbitraje para controlar el acceso a recursos compartidos<sup><\/sup>. Funciona como un contador que gestiona un n\u00famero de \u00abllaves\u00bb o \u00abpermisos\u00bb<sup><\/sup>.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>new(keyCount)<\/code>:<\/strong> Crea un sem\u00e1foro con <code>keyCount<\/code> llaves.<\/li>\n\n\n\n<li><strong><code>get(N)<\/code>:<\/strong> Solicita <code>N<\/code> llaves. Si no hay suficientes, el proceso se bloquea hasta que est\u00e9n disponibles.<\/li>\n\n\n\n<li><strong><code>put(N)<\/code>:<\/strong> Devuelve <code>N<\/code> llaves al sem\u00e1foro, permitiendo que otros procesos bloqueados puedan continuar.<\/li>\n\n\n\n<li><strong><code>try_get(N)<\/code>:<\/strong> Intenta obtener <code>N<\/code> llaves sin bloquearse. Devuelve <code>1<\/code> si tiene \u00e9xito y <code>0<\/code> si no.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Aplicaci\u00f3n:<\/strong> Proteger un bus APB de accesos simult\u00e1neos por parte de un proceso principal y un manejador de interrupciones<sup><\/sup><sup><\/sup><sup><\/sup><sup><\/sup>.<\/p>\n\n\n\n<ul start=\"1\" class=\"wp-block-list\">\n<li><strong>Declarar e inicializar el sem\u00e1foro (con una sola llave para el bus):<\/strong><\/li>\n<\/ul>\n\n\n<pre class=\"brush: systemverilog; title: ; notranslate\" title=\"\">\nsemaphore APB_semaph;\ninitial APB_semaph = new(1);\n<\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Proteger el acceso al recurso en las tasks:<\/strong><\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><\/li>\n<\/ol>\n\n\n<pre class=\"brush: systemverilog; title: ; notranslate\" title=\"\">\ntask automatic write_apb;\n\/\/ ... inputs ...\nbegin\nAPB_semaph.get(); \/\/ Espera y toma la llave del bus\n\/\/ --- Secci\u00f3n Cr\u00edtica ---\n\/\/ Acceso al bus APB...\n\/\/ -----------------------\nAPB_semaph.put(); \/\/ Devuelve la llave\nend\nendtask\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Esto garantiza que la operaci\u00f3n de acceso al bus sea <strong>at\u00f3mica<\/strong>, evitando conflictos y condiciones de carrera.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Mailboxes<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Un mailbox es un mecanismo de comunicaci\u00f3n entre procesos, que funciona como una cola FIFO para pasar mensajes<sup><\/sup>.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>new(size)<\/code>:<\/strong> Crea un mailbox. Si <code>size<\/code> es 0, la capacidad es ilimitada.<\/li>\n\n\n\n<li><strong><code>put(message)<\/code>:<\/strong> Coloca un mensaje en el mailbox. Si est\u00e1 lleno, el proceso se bloquea.<\/li>\n\n\n\n<li><strong><code>get(message)<\/code>:<\/strong> Obtiene un mensaje del mailbox. Si est\u00e1 vac\u00edo, el proceso se bloquea.<\/li>\n\n\n\n<li><strong><code>try_put()<\/code> \/ <code>try_get()<\/code>:<\/strong> Versiones no bloqueantes.<\/li>\n\n\n\n<li><strong><code>peek()<\/code>:<\/strong> Lee un mensaje sin quitarlo del mailbox.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Se pueden parametrizar para garantizar que solo se env\u00eden datos de un tipo espec\u00edfico, evitando errores en tiempo de ejecuci\u00f3n<sup><\/sup><sup><\/sup><sup><\/sup><sup><\/sup>.<\/p>\n\n\n<pre class=\"brush: systemverilog; title: ; notranslate\" title=\"\">\n\/\/ Mailbox que solo acepta strings\ntypedef mailbox #(string) string_mbox;\nstring_mbox m = new();\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Aplicaci\u00f3n:<\/strong> Un manejador de interrupciones notifica al proceso principal qu\u00e9 perif\u00e9rico est\u00e1 libre<sup><\/sup><sup><\/sup><sup><\/sup><sup><\/sup>.<\/p>\n\n\n<pre class=\"brush: systemverilog; title: ; notranslate\" title=\"\">\n\/\/ Mailbox para perif\u00e9ricos libres\nmailbox perif_libre;\n\ninitial begin\nperif_libre = new();\n\/\/ Inicialmente, todos los perif\u00e9ricos est\u00e1n libres\nperif_libre.put(1);\nperif_libre.put(2);\nend\n\n\/\/ Proceso principal\n\/\/ Espera a que un perif\u00e9rico est\u00e9 libre\nperif_libre.get(perif_a_atender);\n\/\/ ... atiende al perif\u00e9rico ...\n\/\/ Manejador de interrupciones\nalways @(IRQ) begin\n\/\/ ... lee el vector de interrupci\u00f3n ...\n\/\/ Notifica al proceso principal que el perif\u00e9rico est\u00e1 libre\nperif_libre.put(irq_vector);\nend\n<\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Eventos<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Los eventos son la forma m\u00e1s fundamental de sincronizaci\u00f3n en SystemVerilog<sup><\/sup>.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Declaraci\u00f3n:<\/strong> <code>event mi_evento;<\/code> <\/li>\n\n\n\n<li><strong>Disparo (Trigger):<\/strong> <code>-&gt;mi_evento;<\/code> (disparo bloqueante) <\/li>\n\n\n\n<li><strong>Disparo no bloqueante:<\/strong> <code>-&gt;&gt;mi_evento;<\/code> <\/li>\n\n\n\n<li><strong>Espera:<\/strong> <code>@(mi_evento);<\/code> o <code>wait(mi_evento.triggered);<\/code> <\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Ejemplo cl\u00e1sico:<\/strong><\/p>\n\n\n<pre class=\"brush: systemverilog; title: ; notranslate\" title=\"\">\n\/\/ Declaraci\u00f3n del evento\nevent received_data;\n\n\/\/ Proceso que dispara el evento\nalways @(posedge clk)\nif (last_dat_packet)\n-&gt; received_data;\n\n\/\/ Proceso que espera el evento\nalways @(received_data)\ndata_buf = {data_pkt&#x5B;0], data_pkt&#x5B;1]};\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">SystemVerilog tambi\u00e9n permite operaciones m\u00e1s complejas como esperar una secuencia de eventos (<code>wait_order<\/code>) y fusionar o comparar eventos. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Modelo de Programaci\u00f3n Concurrente en SystemVerilog SystemVerilog introduce nuevas herramientas avanzadas para manejar la concurrencia, esenciales para la verificaci\u00f3n de dise\u00f1os complejos. Ni que decir tiene que hereda toda la concurrencia que hemos visto en Veirlog; pero hace unas incorporaciones y mejoras interesantes- Construcci\u00f3n fork\/join SystemVerilog mejora el fork\/join de Verilog con modificadores que controlan cu\u00e1ndo el proceso \u00abpadre\u00bb contin\u00faa su ejecuci\u00f3n. Ejemplo de Control del join: Sem\u00e1foros Un sem\u00e1foro es un mecanismo de arbitraje para controlar el acceso a recursos compartidos. Funciona como un contador que gestiona un n\u00famero de \u00abllaves\u00bb o \u00abpermisos\u00bb. Aplicaci\u00f3n: Proteger un bus APB de accesos simult\u00e1neos por parte de un proceso principal y un manejador de interrupciones. Esto garantiza que la operaci\u00f3n de acceso al bus sea at\u00f3mica, evitando conflictos y condiciones de carrera. Mailboxes Un mailbox es un mecanismo de comunicaci\u00f3n entre procesos, que funciona como una cola FIFO para pasar mensajes. Se pueden parametrizar para garantizar que solo se env\u00eden datos de un tipo espec\u00edfico, evitando errores en tiempo de ejecuci\u00f3n. Aplicaci\u00f3n: Un manejador de interrupciones notifica al proceso principal qu\u00e9 perif\u00e9rico est\u00e1 libre. Eventos Los eventos son la forma m\u00e1s fundamental de sincronizaci\u00f3n en SystemVerilog. Ejemplo cl\u00e1sico: SystemVerilog tambi\u00e9n permite operaciones m\u00e1s complejas como esperar una secuencia de eventos (wait_order) y fusionar o comparar eventos.<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"ub_ctt_via":"","footnotes":""},"class_list":["post-1757","page","type-page","status-publish","hentry"],"featured_image_src":null,"_links":{"self":[{"href":"https:\/\/dsd.webs.upv.es\/index.php?rest_route=\/wp\/v2\/pages\/1757","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dsd.webs.upv.es\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/dsd.webs.upv.es\/index.php?rest_route=\/wp\/v2\/types\/page"}],"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=1757"}],"version-history":[{"count":4,"href":"https:\/\/dsd.webs.upv.es\/index.php?rest_route=\/wp\/v2\/pages\/1757\/revisions"}],"predecessor-version":[{"id":1907,"href":"https:\/\/dsd.webs.upv.es\/index.php?rest_route=\/wp\/v2\/pages\/1757\/revisions\/1907"}],"wp:attachment":[{"href":"https:\/\/dsd.webs.upv.es\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1757"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}