¿Es mejor arreglar las x en la simulación o en el diseño?

Tengo una pregunta sobre cómo lidiar con las x en las simulaciones de listas de conexiones de Verilog. Tengo un desacuerdo con otro ingeniero (que es un poco mayor que yo) sobre cuál es el enfoque correcto. Aunque esta pregunta puede parecer basada en una opinión, creo que hay una respuesta correcta incluso si las opiniones están divididas.

Hago desarrollo para ASIC de señal mixta. Estoy haciendo simulaciones de netlist de un microprocesador que no tiene sus registros de programa reiniciados (es un ARM Cortex-M3, hay una opción para no reiniciar los registros durante la síntesis).

Tenemos una ROM desde la que el procesador comienza a ejecutarse después del reinicio. Durante la ejecución de ese programa, un registro de programa (R6) tiene x porque no se restableció. En un punto de la simulación, las x de ese registro se propagan como un reguero de pólvora por el resto del diseño y rompen la simulación. No vemos este problema en las simulaciones RTL.

Preferiría hacer un cambio de diseño para hacer que los registros se restablezcan o que el programa ROM escriba ceros en esos registros a primera hora. Mi universidad es muy reticente a realizar cualquier cambio de diseño para borrar estas x, y preferiría enmascararlas en la simulación de alguna manera.

Su argumento es que "las x no son reales porque las x no existen en el hardware real". Por lo tanto, concluye que las x en la simulación no son reales, y que cualquier cambio de diseño basado en estos no es algo bueno, o al menos, una respuesta demasiado extrema.

Mi argumento es que, aunque es indudable que las x no existen en el hardware, representan valores desconocidos o impredecibles. Creo que la biblioteca de puertas modela x para propagarse de manera pesimista. Por lo tanto, si las x se propagan para matar la simulación, sugiere que podría haber una combinación de bits que podría causar un problema. Dado que esa es una posibilidad, no veo que hacer un cambio de diseño para borrar las x sea demasiado extremo, incluso si no puedo probar que son absolutamente reales. (Supongo que podría intentar una búsqueda de la mala combinación de bits, pero eso sería mucho trabajo).

Ahora, puedo imaginar una respuesta de que el enfoque correcto depende del tipo de calidad que se está desarrollando aquí. Pero creo que los cambios de diseño que he sugerido (agregar los reinicios o borrarlos en el programa) cuestan muy poco (especialmente modificar el programa ROM). Creo que pasar por el proceso de enmascarar los bits en la simulación sería mucho más laborioso.

¿Qué podría estar malinterpretando desde su punto de vista? ¿Cuál es el mejor enfoque? ¿Es realmente tan malo hacer un cambio de diseño para un problema que no puede probar que sea absolutamente real?

Respuestas (3)

Supongo que depende de dónde xestén los 's en el diseño.


Tome un esquema de comunicación de ejemplo dentro del chip. Es posible que desee pasar datos entre dos componentes, pero digamos que no en cada ciclo de reloj. Entonces podría decidir tener un bus de datos y una señal válida. La señal válida dice cuando los datos son válidos. Debido a esto, siempre que la señal válida sea baja, el valor de la señal de datos no importa (porque se ignora).

En este ejemplo, siempre que la señal válida nunca sea un "no importa", el diseño nunca hará nada inesperado. La señal de datos puede ser indiferente, realmente no importa, porque siempre se sabe que habrá datos válidos (cualesquiera que sean) cuando la señal válida sea alta.

Si la señal válida alguna vez fue no importa, entonces tienes un problema. ¿Por qué? porque significa que tienes un escenario en el que no tienes idea de lo que sucederá. Esto puede o no causar un problema, pero es una pesadilla rastrearlo.


Entonces, con eso en mente, es mi opinión que:

Si te encuentras con x's en un bus de datos, no es el fin del mundo, en realidad no sabes cuáles serán los datos en un momento dado de todos modos.

Si aparecen en las señales de control puede que sea malo o no, no lo sabes. En esta situación, debe ejecutar su simulación dos veces, una vez asegurándose de que el don't care sea forzado a ser 0, y la segunda vez asegurándose de que sea un 1. De esta manera, sabrá lo que sucederá en ambos casos .

Si no puede estar seguro (es decir, a partir del código que ha escrito) de que un "no importa" no causará problemas, entonces no debe ignorarlo, xes un desastre potencial desconocido. Si sabe que el valor en cualquier punto dado no importa, entonces xes perfectamente válido.



Además, todos los registros de control, para lo que sean, deben inicializarse a un valor en el reinicio. Un registro de control no inicializado en el encendido podría ser desastroso. Imagina que creas un sistema de control para el lanzamiento de armas nucleares y no inicializaste el registro de 'lanzamiento' en 0. Por lo que sabes, cuando enciendes la energía, podrías comenzar la Tercera Guerra Mundial.

Hay muchas causas diferentes para el estado X en una simulación, pero desafortunadamente todas están representadas por un estado en Verilog. VHDL tiene el estado U para representar un valor no inicializado. Puede que eso no tenga una representación física en el hardware, pero ciertamente es una propiedad real de un diseño de hardware además del nivel de voltaje de la señal.

La propagación precisa del estado X es una simulación dinámica difícil para cualquier RTL o netlist. Es posible que desee buscar herramientas formales para este propósito, especialmente para la verificación de reinicio. Son muy adecuados para esta aplicación para probar exhaustivamente todas las combinaciones.

En cuanto al costo asociado con agregar lógica de reinicio, los diseños siempre tienen algún tipo de límite en su especificación; potencia, area, caracteristicas. Por lo tanto, ciertamente no desea agregar lógica innecesaria para que su simulación de lista de red funcione. Algunos simuladores le permiten inicializar aleatoriamente la lógica, por lo que al menos puede obtener cierto nivel de confianza antes de intentar enmascarar las X.

Si está ejecutando código generado por un compilador 'C' (en lugar de un ensamblador sin procesar) en un núcleo ARM, es probable que tenga problemas con las simulaciones de netlist a menos que comience inicializando el banco de registros. Dependiendo de cuán agresivo haya sido el compilador, es posible que deba inicializar todos los estados (y esto luego comienza a ser riesgoso).

The most obvious problem is that flag-setting operations on in-initialised registers will move a fairly harmless data-path X into the control path in a way that isn't always harmless. This isn't something that should happen in sensibly hand-written code, but the 'C' compiler is (I think) at liberty to re-order operations and sometimes do things where it will ignore the result. The RTL will behave consistently if it's given arbitrary numeric input, but sometimes reacts badly if it's given X as a data value.

As soon as you have prefetch logic which is exposed to X data, it's not hard to imagine that more control logic can generate an X result instead of a fast/slow type of performance behaviour.

RTL se escribe con frecuencia para ser X-pesimista, por lo que cualquier valor X (que represente valores desconocidos) se pasará a través de un diseño.

Si sus pruebas se ejecutan sin inicializar el banco de registros a 0 en su código de inicio, manténgalo así. Es más probable que detecte un problema de esta manera (como ejecutar la imagen del código para ejecutar datos). Sin embargo, no se desespere si tiene que inicializar algunos registros en el software solo para ejecutarlos en una lista de conexiones.

Si encuentra que su netlist necesita que todos los fracasos se inicialicen en el reinicio, debe consultar la documentación principal (manual de integración) y hacer un seguimiento con soporte si es necesario.

Para respaldar esta vista, busque en el código de arranque proporcionado con el banco de pruebas de ejecución. Si hay algunas inicializaciones de cero allí, las necesitará para la simulación de netlist (pero probablemente no en silicio real).