Verificación de CPU blanda

Actualmente estoy en el proceso de diseñar una CPU simple en VHDL usando Xilinx ISE e ISIM. La parte del diseño va notablemente bien, pero parece que no puedo encontrar una manera de hacer la verificación de manera consistente.

Ahora mismo tengo un banco de pruebas de VHDL que actualizo para probar la función en la que estoy trabajando en cada momento. Esto es muy ad-hoc y no me ayuda a detectar regresiones y no se puede usar para verificar el cumplimiento de la especificación/conjunto de instrucciones.

He pensado en desarrollar un amplio conjunto de pruebas, pero el problema es que el estado potencial de una pieza de uso general como CPU es enorme en comparación con componentes menos genéricos.

Estoy buscando un método que me permita realizar el diseño y las pruebas de una manera más controlada. Algún tipo de "TDD de hardware" por así decirlo. ¿Existe tal cosa? ¿Se puede aplicar con relativa facilidad a piezas de propósito general como una CPU?

Respuestas (1)

Todo el tema de la verificación de la CPU es muy grande y difícil. Hay gente que hace carrera solo con esto. Solo te daré un resumen...

  1. Escriba un programa en lenguaje ensamblador que pruebe cada instrucción y cada pequeño detalle de cada instrucción. Por ejemplo, al probar la instrucción ADD, puede probarla con números que sean positivos, negativos y uno de cada uno (dos veces). Luego, probaría la bandera de acarreo, la bandera cero, etc. Otras características especiales de la CPU (como la predicción de bifurcación, etc.) tendrían su propia parte especial de esta prueba.

  2. Escribe, usando C/C++ o algo así, un modelo de tu CPU. Esta es su CPU virtual. Esta es también su "CPU dorada", lo que significa que esta es la CPU con la que se compara todo lo demás. Idealmente, la persona que escribió el VHDL NO es la misma persona que escribe el modelo C/C++.

  3. Escriba/cree un sistema en el que pueda ejecutar el modelo C/C++ y el modelo VHDL uno al lado del otro, y compare los resultados ciclo por ciclo. Ejecute su programa de ensamblaje desde el Paso 1 y asegúrese de que los dos modelos coincidan.

  4. Ejecute sus dos modelos en "instrucciones" aleatorias. Básicamente, llene "ram" con datos aleatorios y ejecute esos datos aleatorios como si fueran instrucciones reales. Ejecute los mismos datos aleatorios en modelos VHDL y C/C++ y compare los resultados. Este modelo C/C++ se ejecutaría en alguna estación de trabajo y/o servidor (no en la nueva CPU).

  5. Configure una máquina, o varias máquinas, para repetir el paso 4 esencialmente para siempre. Incluso si su CPU está "terminada" y ha estado en producción durante un año o más, seguirá ejecutando esta prueba.

  6. Repita estos pasos cada vez que haya más cosas para simular. Por ejemplo, lo ejecutaría en el VHDL posterior a la ruta con sincronización cuando esté disponible.

No hay garantía de que la comparación de las versiones VHDL y C/C++ detectará todos los errores, pero realmente no hay una mejor manera. Y probar la CPU con instrucciones aleatorias lleva tiempo, pero eso también es muy útil. La única alternativa real a esto es contratar a mucha gente para escribir código todo el día para probar diferentes partes de la CPU, y las compañías más grandes hacen esto, pero también hacen cosas de datos aleatorios.

Para una sola persona que escribe código VHDL, generalmente solo se realiza el paso n. ° 1. Pero si va a vender la CPU, debe realizar al menos algunos de los otros pasos (y realmente, debe hacerlos todos).

Excelente respuesta, gracias! Esto tiene mucho sentido. La "CPU dorada" es, de hecho, la pieza faltante del rompecabezas que le permite realizar una verificación ciclo por ciclo durante las pruebas. Dado que este es principalmente un proyecto de juguete, creo que me ajustaré a la primera oración del último párrafo y solo haré el paso #1. Pero saber lo que debería estar haciendo es invaluable.
También puede tener un modelo de C++ dorado, pero sin precisión de ciclo, que permite que sea mucho más simple y, por lo tanto, más probable que sea correcto, útil para probar la funcionalidad de ALU, por ejemplo ("2 + 2 = 4 y algunas banderas, yo no importa cuándo" en lugar de "2+2=4 después de un tic y las banderas después de 2 tic")
Además, ejecute la cobertura de código (para comprobar que lo ejercitó todo) y la cobertura de prueba (para comprobar que todas las pruebas se han probado tanto para pasar como para fallar)
Seguimiento: usando el procedimiento del "paso uno", logré encontrar muchas fallas... en mi ensamblador: P El núcleo en sí parece estar relativamente bien.