2020/11/08

PYNQ con acelerador

En pocas palabras para no repetir lo dicho antes:

 

Necesito hacer un acelerador criptográfico en la PL (Programmable Logic) de un Zynq-7020 (PYNQ en particular) accesible desde un programa que se ejecute en el PS (Processing System) o como todos le conocemos, CPU.

Ya había logrado usar IP (la forma en que llaman a los componentes en este mundo), en particular dos UARTs. Ahora quiero hacer mi propia IP y que haga un cirfrado sencillo.

No voy a apoyarme en una experiencia anterior con Parallella sino en los ejercicios del libro comentado que he estudiado.

 

Estos proyectos están a la par de los dos proyectos "serial" y "dual-serial"  y también lo construiré de cero sin ninguna dependencia cruzada para evitar complicaciones, apuntando a las siguientes hitos:


  • Acelerador echo: que me devuelva lo que escribo.
  • Acelerador xor: que calcule el xor de dos argumentos en un tercero.

 

 

Acelerador con eco 


Manos a la obra, esta parte es común a todos los proyectos anteriores:

  • Create Project
  • RTL Project
  • Target Language Verilog
  • Skip add files
  • Skip add constraints
  • Default Part
  • Boards
  • Seleccionar pynq-z2
  • Agregar el xdc, que es el mapeo de los pines a la FPGA

 

Acá empieza la diferencia, crear el IP

  • Tools -> Create and Package New IP
  • Create a new AXI4 peripheral
  • Name, version, etc...
  • Next Steps -> Edit IP
  • Finish

 

Ahora se pone delicado, hay que buscar el archivo que te creó y al final hay un comentario que dice "Add user logic here", nada por ahora.


Edición del acelerador
Edición del acelerador




Más arriba, buscando "slv_reg0" encontras los nombres de los registros para comunicarte con la CPU. Son todos de 32 bits.

Voy a usar

  • slv_reg0 como clave
  • slv_reg1 como input
  • slv_reg2 como output 
  • slv_reg3 como contador, ya que está...

 


Lo primero que tengo que hacer es que me funcione como memoria, o sea, escribo algo y luego lo vuelvo a leer. Si está ok, estamos encaminados, sigamos entonces.

Hay que ir al tab:

  • Package IP - accelerator
 Abajo de todo va a estar

  • Re-Package IP

 

Listo, cerró, volvemos al proyecto original.

  • Create Block Design
  • Add IP
  • Zynq
  • run block automation 
  • Add IP
  • Buscar el nombre, en este caso accelerator
  • run connection automation
  • Save Block Design
  • Tools -> Validate
  • Sources -> Design Sources -> tu proyecto -> botón derecho -> Create HDL Wrapper
  • Generate bitstream
  • File -> Export Hardware
    • include bitstream
  • File -> Launch SDK

 

Lo que queda es puro software

  • File -> New -> Application Project
  • Templates -> Empty

 

Para encontrar la dirección del acelerador, hay que mirar system.hdf:


Dirección del acelerador
Dirección del acelerador

 

Con este sencillo programa pruebo que funciona, lo que escribo lo puedo volver a leer:

 

#include <stdio.h>
#include "xil_printf.h"
#include "xil_io.h"

#define BaseAddress    0x43c00000
#define REG_KEY        0
#define REG_CLEARTEXT  4
#define REG_CIPHERTEXT 8


int main() {
  u32 key;
  u32 clearText;
  u32 cipherText;

  xil_printf("Accelerator\n\r");
  for (u32 i=0; i< 255; ++i) {
    key        = Xil_In32(BaseAddress + REG_KEY);
    clearText  = Xil_In32(BaseAddress + REG_CLEARTEXT);
    cipherText = Xil_In32(BaseAddress + REG_CIPHERTEXT);

    xil_printf("i          : %d\n", i );
    xil_printf("key        : %d\n", key );
    xil_printf("clear text : %d\n", clearText );
    xil_printf("cipher text: %d\n", cipherText );

    Xil_Out32(BaseAddress + REG_KEY, i);
    Xil_Out32(BaseAddress + REG_CLEARTEXT, i);
    Xil_Out32(BaseAddress + REG_CIPHERTEXT, i);
    sleep(5);
  }
  return 0;
}


La ejecución en la terminal:



echo Ok
echo Ok
 

Acelerador XOR

 

Recorrí un tortuoso camino, con muchas pruebas fallidas. Cuando finalmente me rendí y busqué en internet, lo primero que hallé fueron estos minutos de 4 a 8, que tampoco funcionó, hasta que me dí cuenta de mi error:

#define BaseAddress    0x43c0000


¿Lo viste? Me quería matar, bueno, no importa, pensé bastante, el acelerador funciona y recorrí el camino de editar IP y reintegrarlo hasta el aburrimiento. Prometo que voy a hacer un machete de cómo hacer esto, pero despues, en diciembre que ahora estoy hasta las manos.

 

Nota del futuro: el paso anterior de echo también tenía ese problema, pero no se manifestó pues la dirección errónea no coincidió con nada que se pudiera romper. Lo corregí y dió ok.


El código Verilog, en verde mis agregados y modificaciones:


Código Verilog xor
Código Verilog xor

Los dos bloques calculan tanto el xor como el incremento del contador, cuyos registros están conectados a los Out que permanentemente están conectados a los registros 2 y 3. No me gusta mucho pues claramente el contador está contando el clock, no la cantidad de pedidos de cifrado y el exor se hace en cada ciclo de clock, es demasiado veloz, qué pasa si quiero hacer un cifrado de verdad que no llegue a hacerse en tal breve intervalo o si quiero hacer el ataque pensado? Bueno, eso esa el próxima entrega o la siguiente...

 

El programa tal como está ahora:


#include <stdio.h>
#include "xil_printf.h"
#include "xil_io.h"

#define BaseAddress    0x43c00000
#define REG_KEY        0
#define REG_CLEARTEXT  4
#define REG_CIPHERTEXT 8
#define REG_COUNT      12

int main() {
  u32 key;
  u32 clearText;
  u32 cipherText;
  u32 count;

  xil_printf("Accelerator\n\r");

  Xil_Out32(BaseAddress + REG_KEY, 3);

  for (u32 i=0; i< 255; ++i) {
        Xil_Out32(BaseAddress + REG_CLEARTEXT, i);

    key        = Xil_In32(BaseAddress + REG_KEY);
    clearText  = Xil_In32(BaseAddress + REG_CLEARTEXT);
    cipherText = Xil_In32(BaseAddress + REG_CIPHERTEXT);
    count      = Xil_In32(BaseAddress + REG_COUNT);

    xil_printf("i          : 0x%08x\n", i );
    xil_printf("key        : 0x%08x\n", key );
    xil_printf("clear text : 0x%08x\n", clearText );
    xil_printf("cipher text: 0x%08x\n", cipherText );
    xil_printf("count      : 0x%08x\n", count );

    sleep(5);
  }
  return 0;
}

 

Y la salida, comparando con lo esperado en la calculadora:


Ejecución Ok
Ejecución Ok


 



No hay comentarios:

Publicar un comentario