Verificación,  Verificación funcional

RCSG y cobertura funcional en microprocesadores

He creado esta entrada para que pensemos cómo podemos utilizar RCSG y covergroups en la verificación de un microprocesador.

Una forma que se me ocurre de hacerlo (y desde luego no es única) es la que os voy a describir. Es el momento adecuado porque empezamos esta semana a conocer el código máquina de los diferentes tipos de instrucciones del RISC-V que tenemos entre manos.

RCSG

Lo primero que pensé 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é que quizá fuera interesante modelizar la memoria ROM con dos estilos: Estilo sintetizable directo y estilo random.

  • El primero utilizaría el clásico txt para inicializar el contenido y debería ser sintetizable por quartus sin problemas.
  • El segundo generaría cada vez que el “address” cambiara un contenido gobernado por una clase RCSG, intentando claro está que si volviera a repetirse algún “address” el contenido aleatorio se repitiera.

Puede verse estos dos estilos separados mediante una compilación condicional en la que elijamos o el comportamiento directo sintetizable o el comportamiento aleatorio.

Vamos a centrarnos en el comportamiento aleatorio (desde la línea 16 hasta la 26) que tiene más elementos nuevos.

  1. Cada vez que always se reanuda y ejecuta por un cambio de “address”, obtenemos desde un “mailbox” denominado m1 un valor “random”
    • Para ello una cierta infraestructura es necesaria, como por ejemplo la declaración 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ón “program” donde centralizaremos todos los elementos de test. Mas adelante veremos esas sintaxis. Lo que si que adelanto es que evidentemente el valor “random” lo conseguiré por el uso del método randomize que ya todos conocéis.
    • Otra cosa que necesitamos es un pequeño diccionario (implementado con un array asociativo) que asocie una dirección con un valor aleatorio, de forma que si el microprocesador transitara de nuevo por la misma dirección, detectemos que ese “address” ya ha sido utilizado y reusemos el valor aleatorio generado la primera vez que ese address se utilizó (el valor procedente del mailbox se lee para vaciarlo, aunque no se usa).

Veamos como sería la clase donde generamos el valor aleatorio.

He creado unos “constraints” para conseguir unas instrucciones de tipo R_format. la primera de esas constraints elige un tipo de instrucciones y deberá habilitarse o deshabilitarse según convenga, mientras que las dos siguientes “constraints” son derivadas de la anterior y pueden estar siempre habilitadas.

Ya solo nos quedaría ver cómo usamos dicha clase. Este uso lo vamos a centralizar en el test (realizado con un program).

En este código se puede observar la generación del valor aleatorio y su escritura en el “mailbox” m1, cada vez que vamos a generar un nuevo address. Previamente hemos hecho la declaración (línea 3) y la creación (línea 10) del objeto que habíamos visto su definición en el código Clase RCSG.

En cuanto a la línea 19, podemos ver como escribir los contenidos aleatorios en un fichero txt para su posterior uso.

Cobertura funcional

Volvamos al código anterior y ya se vislumbra la declaración (línea 4) y creación (línea 11) del covergroup necesario para monitorizar las instrucciones. Solo nos faltaría visualizar la definición del covergroup que tenemos en la siguiente sección de código:

Comentemos algunos detalles:

  • El covergroup como era de esperar es inmediato y requiere del uso del método “sample” para determinar el momento de muestreo. Ver lineas 29 y 36 del código del program en donde utilizamos dicho método de muestreo.
  • He puesto al coverpoint de una condición de enable (iff) que me permita habilitar únicamente el cubrimiento de esas combinaciones de código cuando estemos realmente en una instrucción r_format.
  • Recurro a un interface virtual para poder obtener la monitorización del puerto de salida de la ROM. Ya lo habíamos hecho en otros ejemplos y he recurrido a una estructura muy parecida a la utilizada en el ejemplo final de la verificación del radicador

Estructura completa

Ya solo nos quedan los detalles. El primero es que las dos clases utilizadas las he puesto en un paquete con el nombre de utilidades_verificacion.

Para la monitorización de los puertos de salida ha sido esencial la definición de un interfaz que todo lo una. Un interfaz con los típicos tres modos que ya hemos utilizado en otros ejemplos y en el que destaca la ausencia de elementos de sincronización (clocking blocks) . Eso puede suponer un problema que puede ser subsanado con técnicas manuales de sincronización como es la utilización del cero delay visible en las líneas 29 y 36 del program. Esta técnica me garantiza que cuando monitorizo el puerto de salida en un instante en que ese puerto debe cambiar, el valor que monitorizo será el nuevo generado puesto que pospongo la lectura de muestreo al final de ese instante.

Por supuesto la utilización del interfaz me obliga a encapsular el duv en un livel jerárquico superior que utilice dicho interfaz

Ya solo nos queda el banco de pruebas (top de nuestra jerarquía) en donde destacará la declaración y construcción del mailbox que vamos a utilizar para intercomunicar los procesos de los estímulos (program) con los del duv (modelo de la memoria aleatorizada)

Y para terminar un último detalle. Este comportamiento aleatorio de la ROM solo será efectivo si cuando compile con vlog defina la variable “debug_aleatorio”. Si hago una compilación con las opciones por defecto actuará la ROM sintetizable y cargada desde un txt y por tanto sin ningún tipo de aleatorización. La forma de compilar con esa definición de variable es:

vlog +define+debug_aleatorio rom_aleatoria.sv

Veamos con el siguiente vídeo el comportamiento de esta simulación:

Para que podáis probar el proyecto adjunto el mismo en le siguiente laboratorio virtual:

[iframe width=”100%” height=”480″ src=”https://www.edaplayground.com/x/jztC”]

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *