Introducción
Esta es la segunda entrada de una serie de cuatro sobre la reconfiguración parcial (partial reconfiguration; también Dynamic Function eXchange, DFX) con Vivado de Xilinx. La intención de esta entrada es repasar y explicar los pasos para habilitar la reconfiguración parcial en un diseño de FPGA. Si aún no lo has hecho, es recomendable leer la primera entrada, donde se explican los conceptos en los que se basan estos pasos.
Xilinx renombró la reconfiguración parcial como "Dynamic Function eXchange" (DFX) en 2020. DFX es la expresión que aparece en los menús y notas informativas de Vivado. No obstante, aquí se usa el término técnico "reconfiguración parcial".
Para simplificar, esta entrada supone que el proyecto tiene una única partición reconfigurable. Ampliarlo a varias particiones es bastante sencillo.
El procedimiento descrito en esta entrada comienza antes de que el proyecto se haya habilitado para la reconfiguración parcial. Así que, a grandes rasgos, los pasos son:
- Preparar el proyecto para la planificación física
- Hacer una configuración inicial del proyecto para la reconfiguración parcial
- Planificación física
- Comprobar y corregir la planificación física con una implementación del diseño
- Añadir un segundo módulo reconfigurable (o varios)
- Realizar la implementación para obtener los archivos de flujo de bits
- Revisar el proyecto
Preparación para la planificación física
La planificación física (floorplanning) es, más que cualquier otra tarea, la que exige trabajo intelectual. Es un equilibrio sutil entre no malgastar área de lógica de la FPGA y asegurarse de que tanto la partición estática como las particiones reconfigurables no tengan obstáculos importantes durante la colocación y el encaminamiento (place and route).
Por eso, la mayor parte de esta entrada trata sobre este tema.
En un pasado lejano, la planificación física era una técnica que se usaba para el cierre de temporización (timing closure). Ayudaba a las herramientas a colocar la lógica de forma sensata. Como las herramientas de diseño de FPGA han mejorado con el tiempo, han pasado muchos años desde la última vez que vi que la planificación física ayudara a cumplir las restricciones de temporización (timing constraints). Hoy en día, la mejor estrategia para cumplir las restricciones de temporización es casi siempre dejar que las herramientas tomen las decisiones.
Con la reconfiguración parcial, la planificación física es obligatoria, así que el objetivo no es empeorar las cosas. Hacerlo bien suele ser cuestión de prueba y error. Sin embargo, el método más simple para obtener buenos resultados es realizar una implementación del diseño sin planificación física y, a continuación, partir de cómo se coloca la lógica de forma natural. El siguiente paso es intentar organizar las zonas de una manera que tenga sentido para la reconfiguración parcial, usando la colocación inicial de la lógica como guía.
En el escenario de uso tipo plugin, la planificación física se puede actualizar a medida que el proyecto evoluciona. No ocurre así en el escenario de actualización remota (Remote Update), es decir, cuando la reconfiguración parcial se utiliza como medio para actualizar por versiones un diseño que ya se ha publicado: con la actualización remota, todos los flujos de bits parciales deben corresponderse con el flujo de bits inicial. Por consiguiente, la lógica estática del diseño queda congelada en cuanto se publica el flujo de bits inicial. Eso significa, entre otras cosas, que la planificación física debe permanecer igual.
Así que, incluso antes de empezar con la reconfiguración parcial, la primera tarea consiste en encontrar un área adecuada en la FPGA para la lógica estática. No merece la pena perder demasiado tiempo en esto: solo hay que obtener el punto de partida para continuar después de dividir el proyecto en dos partes.
No te confundas: el propósito de este primer paso no es la planificación física en sí, sino ver cómo coloca Vivado la lógica sin restricciones y, a partir de ahí, decidir qué zona debe asignarse a la lógica estática. Los pasos son:
- Realiza una implementación del diseño como siempre. Abre el diseño implementado y mira la vista del dispositivo. Hazte una idea de cuántos recursos lógicos consume el diseño estático y cómo prefiere Vivado colocarlos.
- Puede resultar más fácil si las partes que se pretende que sean lógica reconfigurable se retiran temporalmente del proyecto (pero de manera que la lógica estática no se elimine también por optimización lógica).
- Asegúrate de que no haya ningún elemento lógico seleccionado en la vista del dispositivo; haz clic con el botón derecho en algún lugar sobre ella y elige «Draw Pblock». Dibuja una región que parezca adecuada para albergar la lógica estática. No imites necesariamente la colocación que hizo Vivado; intenta más bien encontrar una forma que ocupe un área mínima sin crear obstáculos para la colocación de la lógica ni para cumplir las restricciones de temporización.
- Vivado abrirá un cuadro de diálogo que dice «Create a new Pblock». Puede que sugiera definir el Pblock por regiones de reloj; si es así, no lo hagas. Pide que el Pblock se base en slices, DSP y, posiblemente, otros elementos lógicos.
- En FPGA Ultrascale, el cuadro de diálogo del Pblock también puede sugerir incluir IOB. Si es así, desmarca esa opción, o Vivado podría quedarse bloqueado más tarde al guardar o redimensionar el Pblock (debido a un bug de Vivado).
- Presta atención a la forma del Pblock, en particular al rango de slices. Esta información se puede obtener del panel de propiedades del Pblock en la interfaz gráfica de Vivado (en la pestaña «General») o desde la consola Tcl, donde se escribirá algo como esto:
startgroup create_pblock pblock_1 resize_pblock pblock_1 -add {SLICE_X108Y148:SLICE_X149Y249 DSP48_X4Y60:DSP48_X5Y99 RAMB18_X4Y60:RAMB18_X6Y99 RAMB36_X4Y30:RAMB36_X6Y49} endgroup - Si hay avisos en la consola Tcl, ignóralos.
- Al cerrar el diseño implementado, Vivado preguntará si debe guardarlo. Elige «No», porque el Pblock que acabas de crear no sirve para nada.
Configurar un proyecto para la reconfiguración parcial
El documento UG909 de Xilinx sugiere dos procedimientos de trabajo para la reconfiguración parcial:
- El flujo sin proyecto (non-project flow, en su capítulo 3), es decir, la implementación se realiza escribiendo y ejecutando scripts Tcl explícitamente.
- El flujo con proyecto (project flow, en el capítulo 4), que corresponde a usar la interfaz gráfica de Vivado y los scripts que esta genera automáticamente.
Voy a usar aquí el flujo con proyecto, aunque tiene algunas limitaciones, algunas de las cuales tienen que ver con el tipo de fuentes del módulo reconfigurable (en particular, con el uso de block designs). En cualquier caso, es mejor empezar con el flujo con proyecto, porque los scripts que genera para la implementación son una buena base para el flujo sin proyecto, si hiciera falta.
Estos son los pasos para activar el soporte de reconfiguración parcial en un proyecto existente:
- Selecciona Tools > Enable Dynamic Function eXchange… y haz clic en «Convert». La interfaz se asegurará de que sepas que convertir el proyecto al flujo de reconfiguración parcial es irreversible, así que acepta. El comando Tcl que se ejecuta en realidad es:
set_property PR_FLOW 1 [current_project]
- Decide cuál es el módulo de nivel superior de la partición reconfigurable y haz clic con el botón derecho en su archivo fuente, en el panel Sources del Project Manager de Vivado. Elige «Create Partition Definition…». Esta opción solo está disponible después de habilitar DFX, y eso acabas de hacerlo.
- Aparece un cuadro de diálogo «Create Partition Definition» que pide dos cosas: el nombre de la definición de partición (Partition Definition), que se usará para referirse a esa jerarquía dentro de la lógica. Este nombre se referirá al lugar de la jerarquía donde se pueden insertar distintos módulos reconfigurables. Un nombre adecuado podría ser «pr». La segunda cosa, Reconfigurable Module Name, indica qué lógica va en la partición. Así, por ejemplo, si la reconfiguración parcial se usa para sustituir un filtro de audio, una elección sensata para Reconfigurable Module Name podría ser «lpf», «bpf», «hpf», de modo que cada nombre indique qué filtro se aplica. Puede ser el nombre del módulo de nivel superior, si eso ayuda a entender qué hace.
- La fila del módulo elegido en la lista Sources aparecerá ahora con un rombo amarillo, junto con el nombre del módulo y el de la instancia (por ejemplo, «pr_block» y «pr_block_ins»), tal como se definen en el archivo Verilog o VHDL. Estos nombres no dicen nada sobre qué lógica se inserta en la partición, sino que reflejan el nombre que tienen en el HDL. La partición y el módulo reconfigurable se pueden encontrar en la pestaña «Partition Definitions» del mismo panel Sources.
- Si el módulo reconfigurable contiene instanciaciones de IP (por ejemplo, una FIFO), la IP se puede añadir haciendo clic con el botón derecho en su fila dentro de las fuentes del proyecto principal (en el panel «Hierarchy») y seleccionando «Move to configurable module…». El equivalente en Tcl es algo así como:
move_files -of_objects [get_reconfig_modules lpf] [get_files /path/to/blkmem.xci]Al hacerlo, la IP se mueve a la pestaña «Partition Definitions». - No solo eso: la pestaña «Partition Definitions» funciona como una colección de jerarquías de fuentes para cada módulo reconfigurable. Por ejemplo, para añadir archivos HDL que necesite un módulo reconfigurable, haz clic en «+» en esta pestaña.
- Cuando el módulo reconfigurable esté configurado, define la implementación padre (Parent Implementation). Consulta la entrada anterior sobre implementaciones padre, implementaciones hijas y el asistente:
- Selecciona Tools > Dynamic Function eXchange Wizard.
- Haz clic en Next en la página de bienvenida y en la página de edición de módulos reconfigurables.
- En la página «Edit Configurations», haz clic en «+» para añadir una configuración. El nombre config_1 por defecto está bien, porque no importa demasiado. Por defecto, Vivado selecciona correctamente el módulo reconfigurable para config_1; no es de extrañar, ya que de momento es el único.
- La siguiente pantalla es para añadir ejecuciones de configuración: no hagas nada ahí (por ahora).
- Termina el asistente.
Si intentas implementar el proyecto en este punto, lo más probable es que falle con un error parecido a: «[DRC HDPR-30] Missing PBLOCK On Reconfigurable Cell: HD.RECONFIGURABLE cell 'pr_block_ins' must have PBLOCK assigned to itself or its descendant cells». En palabras sencillas, significa que la planificación física es necesaria.
Planificación física
En este punto, el proyecto está configurado lo justo para la tarea de planificación física.
Antes de desglosar esta tarea en pasos pequeños, conviene mencionar algunas cosas que hay que tener presentes:
- La zona de la FPGA para la lógica estática debe ser lo más pequeña posible, pero sin dificultar la colocación y el encaminamiento. Una estimación aproximada de su forma debería haberse obtenido antes (ver «Preparación para la planificación física» más arriba).
- Las formas de la lógica estática y de la reconfigurable deben ser lo más simples posible, preferiblemente rectángulos sencillos u otras formas que no creen dificultades para el encaminamiento.
- El encaminamiento de la lógica estática puede cruzar las zonas de lógica reconfigurable, pero en la mayoría de los casos no ocurre al revés.
- En esta sesión de planificación física se dibuja la forma de la lógica reconfigurable. Debido a los dos últimos comentarios, esta es la forma que debe mantenerse simple.
- Ten en cuenta las posibilidades y limitaciones de planificación física de tu FPGA concreta, tal como se detalla en los capítulos 6 a 8 de UG909. Por ejemplo, si se usa una FPGA de la serie 7, probablemente sea mejor alinear los límites de las zonas con los bordes de las regiones de reloj.
Ahora, paso a paso:
- Lanza la síntesis del proyecto (es decir, inicia la ejecución synth_1). La síntesis del módulo reconfigurable se hará automáticamente como una ejecución fuera de contexto (Out-of-Context, OOC), por ejemplo lpf_synth_1. Las ejecuciones OOC se explican con más detalle en la última entrada.
- Cuando las ejecuciones terminen, abre el diseño sintetizado (la implementación no es posible en este punto, porque no hay ningún Pblock asociado al módulo reconfigurable).
- Dibuja un Pblock para la lógica reconfigurable. A diferencia de la etapa de preparación, debe estar asociado a la lógica reconfigurable. Para ello: asegúrate de que el panel superior izquierdo tenga abierta la pestaña Netlist, y haz clic con el botón derecho en la celda de nivel superior que va dentro de la partición reconfigurable (por ejemplo, «pr_block_ins»). Selecciona Floorplanning > Draw Pblock, y dibuja una zona sobre la FPGA. Las operaciones en la interfaz son las descritas antes (en «Preparación para la planificación física»). Es decir, la selección se basa en slices y otros elementos lógicos.
- Una vez más, si se sugiere incluir IOB en el Pblock, no aceptes esa sugerencia, o existe la posibilidad de que Vivado se quede bloqueado al procesarlo más tarde.
- No te esfuerces demasiado en esto, porque hay muchas posibilidades de que tengas que corregirlo por las quejas de Vivado. Recuerda una vez más que el Pblock se dibuja para la lógica reconfigurable, y que la lógica estática ocupará la zona restante.
- Ahora ve al panel Pblock Properties. Puede que haga falta hacer clic con el botón derecho sobre el Pblock en la vista del dispositivo y seleccionar Pblock Properties… para que aparezca.
- Selecciona la pestaña Properties (en el panel Pblock Properties).
- Para FPGA de la serie 7 (es decir, no Ultrascale ni posteriores): en el panel Pblock Properties, se recomienda establecer RESET_AFTER_RECONFIG si quieres que la lógica reciba el reset interno de la FPGA después de cargar el flujo de bits parcial (consulta la próxima entrada para más detalles sobre el reset del módulo reconfigurable). Esto crea una restricción XDC como esta:
set_property RESET_AFTER_RECONFIG true [get_pblocks pblock_pr_block_ins]
Esta restricción, entre otras cosas, lleva los biestables a sus valores por defecto. Ten en cuenta, sin embargo, que no tiene nada que ver con los resets definidos en el HDL o en la lógica. Observa también que, en las FPGA de la serie 7, esta función exige que los límites verticales del Pblock estén alineados con las regiones de reloj.
En FPGA Ultrascale y posteriores, este reset está siempre activado. - También existe la propiedad SNAPPING_MODE, que por defecto no está definida en las FPGA de la serie 7 (lo que equivale a OFF). En algunas FPGA probablemente sea necesario ponerla en ROUTING o en ON (que es el valor por defecto para Ultrascale). Volveré a eso más adelante.
- Ahora pulsa CTRL-S para guardar las restricciones (o haz clic en el icono del disquete de la barra superior). Esto añade unas cuantas líneas al archivo XDC, con algo así como:
create_pblock pblock_pr_block_ins add_cells_to_pblock [get_pblocks pblock_pr_block_ins] [get_cells -quiet [list pr_block_ins]] resize_pblock [get_pblocks pblock_pr_block_ins] -add {SLICE_X40Y100:SLICE_X79Y149} resize_pblock [get_pblocks pblock_pr_block_ins] -add {DSP48_X2Y40:DSP48_X2Y59} resize_pblock [get_pblocks pblock_pr_block_ins] -add {RAMB18_X2Y40:RAMB18_X2Y59} resize_pblock [get_pblocks pblock_pr_block_ins] -add {RAMB36_X2Y20:RAMB36_X2Y29} - Cierra el diseño sintetizado.
- Reinicia la ejecución synth_1.
- Intenta generar un flujo de bits (haciendo clic en «Generate Bitstream»). El propósito de esta implementación es comprobar si hay algún defecto en la planificación física; en otras palabras, que Vivado emita avisos críticos (critical warnings) como respuesta a esos defectos. Puede sonar a una forma poco profesional de validar el diseño, pero es fácil y fiable.
Corregir la planificación física
Esta es probablemente la parte menos agradable de la reconfiguración parcial: dejar la planificación física bien ajustada. Si lo haces para el caso de la actualización remota, esta fase es extra importante, porque esa planificación física permanecerá durante toda la vida del proyecto.
Las correcciones en la planificación física son necesarias por dos motivos principales: como respuesta a los avisos críticos, y en una fase posterior para optimizar el uso de la FPGA: el objetivo es reducir el desperdicio de recursos y, al mismo tiempo, evitar crear obstáculos para la colocación y el encaminamiento.
Hacer modificaciones no es difícil, porque basta con arrastrar los bordes de un Pblock. También es fácil ampliar un Pblock con rectángulos adicionales: haz clic con el botón derecho en el Pblock y selecciona «Add Pblock Rectangle».
Los avisos críticos suelen indicar qué correcciones son necesarias; aun así, asegúrate de haber leído el capítulo correspondiente (6, 7 u 8) de la guía de usuario de Xilinx, UG909, sobre las limitaciones de planificación física de tu FPGA concreta.
El resto de esta sección comenta los posibles problemas con FPGA de la serie 7. Con las FPGA Ultrascale es mucho más fácil trabajar.
Un error frecuente con FPGA de la serie 7 es la división de columnas de tiles de interconexión. Por ejemplo:
[Constraints 18-993] The Pblock pblock_pr_block_ins has defined an area that causes the splitting of interconnect tile columns. Dynamic Function eXchange requires that the left and right paired interconnect tile columns cannot be split by a reconfigurable boundary. This is caused by either the left or right edge of a Pblock boundary, or by the Pblock spanning over logic types not included in the Pblock ranges. To avoid an unroutable situation, placement will be prohibited from both of these columns. To avoid placement restrictions, modify the Pblock to avoid splitting the two columns. The column of the split contains interconnect tile INT_L_X48Y299 (SLICE_X79Y299 SLICE_X78Y299). Please refer to the Xilinx document on Dynamic Function eXchange. Resolution: Set the Pblock property SNAPPING_MODE to value of ON, or modify the column/X specification of the pblock to avoid this edge.
y
[Constraints 18-996] The split between the left and right columns occurs between a reconfigurable Pblock and Static logic. The static sites are not reconfigurable. The Pblock should be adjusted to remove the column from the Pblock, unless the excluded reconfigurable and static sites are not needed for the design. Note that adjusting the Pblock will prevent prohibits and improve placement of the design, but may reduce the routability if the removed sites were needed to span across the static logic. Failure to modify the Pblock may lead to an unplaceable design if these prohibited sites are required by the design. Resolution: Set the Pblock property SNAPPING_MODE to value of ON, or modify the column/X specification of the pblock to avoid this edge. and
Para solucionarlo, pon la propiedad SNAPPING_MODE del Pblock en ROUTING o en ON (probablemente ROUTING no baste, así que elige ON), como sugiere el primer aviso. Seguramente esto añadirá muchas restricciones al archivo XDC, de este tipo:
set_property PROHIBIT true [get_sites SLICE_X79Y349] set_property PROHIBIT true [get_sites SLICE_X78Y349] [ ... ] set_property PROHIBIT true [get_sites SLICE_X79Y191] set_property PROHIBIT true [get_sites SLICE_X78Y191] set_property PROHIBIT true [get_sites PMV_X0Y2] set_property PROHIBIT true [get_sites SLICE_X36Y190] set_property PROHIBIT true [get_sites SLICE_X37Y190] [ ... ] set_property PROHIBIT true [get_sites SLICE_X79Y176] set_property PROHIBIT true [get_sites SLICE_X78Y176] set_property PROHIBIT true [get_sites T14] set_property PROHIBIT true [get_sites R15] set_property PROHIBIT true [get_sites XADC_X0Y0] set_property PROHIBIT true [get_sites SLICE_X36Y175] set_property PROHIBIT true [get_sites SLICE_X37Y175] [ ... ]
y continúa.
Los PROHIBIT correspondientes a los slices son los que silencian el aviso crítico mencionado. Las demás asignaciones PROHIBIT se añaden para los emplazamientos lógicos que están dentro de la región geométrica, pero que no están permitidos para la reconfiguración parcial en la FPGA utilizada. Las FPGA Ultrascale y posteriores generan muchas menos líneas con PROHIBIT, si es que generan alguna.
A los solos efectos de silenciar el aviso crítico, probablemente sea aceptable eliminar todas las líneas con PROHIBIT y dejar una sola línea solo para los slices. Esto se hace cubriendo el rango de slices que Vivado añadió como respuesta al cambio en SNAPPING_MODE. Convierte ese rango en algo como:
set_property PROHIBIT true [get_sites -range {SLICE_X79Y0 SLICE_X79Y349}]
Este es el tipo de línea en el archivo XDC que puede resolver el problema de la división de la interconexión sin que el archivo se haga enorme.
Independientemente de lo anterior, también puede aparecer en el archivo XDC una línea de este tipo. Al parecer, también se puede eliminar sin problema:
set_property HD.PLATFORM_WRAPPER true [get_cells pr_block_ins]
Reducir el archivo XDC al mínimo que silencie los avisos críticos puede parecer superficial, pero la alternativa es un archivo de restricciones enorme, que es una receta para la confusión más adelante. Por mi experiencia, la ausencia de avisos de este tipo puede tomarse como una aprobación de que la planificación física del diseño está bien.
Lo más probable es que devolver la propiedad SNAPPING_MODE a OFF vuelva a causar problemas, independientemente de los cambios en el XDC.
Añadir un módulo reconfigurable
Hasta ahora, la implementación consigue prácticamente lo mismo que el diseño jerárquico, con algunas restricciones adicionales. Aunque se genera un flujo de bits parcial, es bastante inútil, porque cargarlo deja el diseño igual.
El objetivo, por tanto, es crear otro flujo de bits parcial basado en otro módulo reconfigurable. Para ello hay que añadir una implementación hija (Child Implementation).
Asegúrate de tener fresca la entrada anterior antes de seguir leyendo, en particular la parte sobre implementaciones padre e hijas y sobre el asistente Dynamic Function eXchange. Recuerda también, como se dijo antes en esta entrada, que la pestaña «Partition Definitions» contiene los módulos reconfigurables definidos y sus fuentes.
Abre el asistente Dynamic Function eXchange desde el menú Tools y haz clic en Next en la ventana de bienvenida.
En la ventana Edit Reconfigurable Modules, haz clic en «+». Se abre un cuadro de diálogo para añadir un módulo reconfigurable. Lo único interesante de este cuadro de diálogo es el Reconfigurable Module Name: es el nombre que se usa para identificar la lógica reconfigurable, como ya se explicó antes.
El cuadro también exige asociar este módulo con el nombre de una definición de partición, pero de todos modos solo hay una (porque esta entrada supone que solo se define una partición).
Hay que añadir al menos un archivo fuente Verilog o VHDL para poder continuar; se pueden añadir más desde la pestaña «Partition Definitions» más adelante. Indicar el nombre del módulo de nivel superior de este módulo reconfigurable no viene mal, sobre todo si no queda claro a partir de los propios archivos fuente.
De vuelta en el asistente, haz clic otra vez en Next, hasta la ventana Edit Configurations. Haz clic en «+» y escribe un nombre de configuración. La única importancia de este nombre es que aparece en la ventana Design Runs. Un nombre como config_2 vale.
Aparece una fila nueva en la lista de configuraciones. Modifica el módulo reconfigurable en la columna correspondiente a la partición, de modo que cada configuración tenga un módulo reconfigurable distinto.
La última ventana es Edit Configuration Runs, para asignar ejecuciones a las configuraciones. La forma fácil es eliminar todas las ejecuciones listadas (si las hay) y hacer clic en «automatically create configuration runs». Eso hace lo que harías manualmente de todos modos: crea una ejecución padre llamada impl_1, y luego crea ejecuciones hijas, nómbralas como quieras y haz que sean hijas de impl_1.
El asistente elige una configuración para cada ejecución, pero es fácil cambiarla. Lo único importante es qué configuración se asocia con la ejecución padre.
Y, por cierto, si eliminas todas las ejecuciones en el asistente, desaparecen todas las hijas, pero impl_1 se queda.
Por fin: implementación del diseño
Para generar los flujos de bits, haz clic en «Generate Bitstreams» en Vivado como siempre. Como ya se mencionó en la entrada anterior, se crean dos o tres flujos de bits para cada configuración en un proyecto de reconfiguración parcial.
Por ejemplo, en una FPGA Ultrascale los archivos de bits pueden ser:
- theproject.bit: El archivo de flujo de bits inicial, con la lógica estática y la lógica reconfigurable correspondiente a la configuración actual.
- pr_block_ins_lpf_partial.bit: El flujo de bits parcial que carga la lógica reconfigurable correspondiente a la configuración actual.
- Solo en Ultrascale existe también pr_block_ins_lpf_partial_clear.bit: el flujo de bits que hay que cargar antes de cargar cualquier flujo de bits parcial, si la configuración actual ya está presente en la FPGA.
Observa que para todas las implementaciones se crea el mismo número de archivos de flujo de bits. En otras palabras, el flujo de bits inicial también se crea para las implementaciones hijas, así que es perfectamente posible cargar la FPGA con el flujo de bits inicial de una de las hijas y continuar a partir de ahí.
Para una forma sencilla de cargar flujos de bits parciales por PCIe o USB 3.x, consulta esta página.
Ninguna de las implementaciones debería tener avisos críticos ni fallar por quejas sobre el Pblock o la planificación física en general, porque esos problemas deberían haberse resuelto antes. Si aun así ocurre algo así, la planificación física debe corregirse como se explicó antes.
A veces, al hacer clic en «Generate Bitstream», si solo se han hecho cambios en las implementaciones hijas, Vivado puede responder: «Bitstream generation has already completed and is up-to-date. Re-run anyway?». Es algo confuso, pero haz clic en «Yes» y las implementaciones hijas se ejecutarán correctamente. Todo este asunto de las implementaciones hijas es una especie de complemento añadido a Vivado, y por eso la fila de estado durante la implementación dice algo como «write_bitstream complete. Child running».
Revisión de los resultados
Como la reconfiguración parcial tiene mucho que ver con la colocación, es buena idea revisar los diseños implementados. Puedes abrir una implementación concreta haciendo clic con el botón derecho en «Open Implemented Design» y pasando el ratón por el elemento del menú que dice «Open Implemented Design» (otra vez). Luego selecciona en la lista qué implementación quieres abrir. Si una implementación no aparece en la lista, probablemente ya está abierta.
Prueba a hacer clic con el botón derecho en la fila superior de la lógica reconfigurable en el panel Netlist de la vista del diseño implementado y elige «Highlight Leaf cells». Haz lo mismo con la lógica estática, con otro color.
Con el mismo clic derecho también está «Show Connectivity», que dibuja líneas rectas blancas entre los elementos lógicos que están conectados. Los caminos de encaminamiento reales en la FPGA son, por supuesto, distintos, así que las regiones de la planificación física que cruzan esas líneas no tienen importancia. Aun así, mirar la conectividad puede ayudar a detectar cuándo la organización general de la planificación física hace que las herramientas tengan que trabajar con dificultad.
Es bastante normal y está bien que algunas celdas que aparentemente pertenecen a la lógica estática aparezcan colocadas dentro de la zona reconfigurable, y viceversa. Lo que debe preocuparte es si parece haber congestión en algún sitio, es decir, si la lógica parece estar demasiado apretada en general o en alguna región concreta. Si es posible, los cambios en la planificación física pueden ayudar a aliviarlo.
Otra cosa que conviene mirar son las posiciones de los pines de partición (partition pins). Aparecen como barras horizontales blancas en la vista del dispositivo, así (haz clic en la imagen para ampliarla):
Como se mencionó en la entrada anterior, los pines de partición pueden estar en cualquier lugar dentro de la partición reconfigurable. Sin embargo, si están lejos de los bordes de la partición, puede indicar que el encaminador tuvo dificultades con la temporización durante la implementación padre.
También es posible obtener una lista de texto con las coordenadas de los pines de partición con este comando Tcl (cambia pr_block_ins por el nombre de la celda de lógica reconfigurable):
foreach s [get_pins -of [get_cells pr_block_ins]] { set partpin [get_pplocs -quiet -pins [get_pins $s]] ; puts "$s => $partpin"; }
Las coordenadas de los pines de partición corresponden a la rejilla de CLB (no a la de slices). En el dibujo mostrado, estos pines aparecen con el nombre de «Cell pins».
Puede que algunos pines de la celda no tengan asignado un pin de partición. Esto ocurre cuando hay un desajuste entre la lista de puertos del módulo reconfigurable (y/o la anchura de los vectores) y su instanciación por la lógica estática. Ese desajuste es perfectamente legal (en Verilog), pero el resultado puede ser no deseado. Ejecutar este comando Tcl permite detectar puertos inaccesibles, sobre todo cuando no es intencionado.
Con esto termina la parte técnica sobre cómo configurar el proyecto en Vivado. Sin embargo, la próxima entrada trata un aspecto importante del diseño de FPGA: cómo asegurarse de que la sustitución de lógica se haga de forma fiable y sin sobresaltos.
