Acceso a DDRAM desde HLS IP (usando MASTER AXI) 2° Cuatrimestre 2015 Patricia Borensztejn Laboratorio 9 11/11/2015 Interfaces AXI4 – AXI4-Lite: para pasar parámetros – AXI4-Stream: para procesar rápido grandes cantidades de datos en forma streaming, como en video por ejemplo – AXI4-Full: para procesar rápido datos: acceso directo a memoria Acceso Directo a Memoria • Para que un IP acceda a Memoria directamente sin pasar por el procesador, usaremos la interface Master AXI. • El IP escribirá o leerá datos de la memoria externa independientemente del procesador. • El procesador se ocupará solo de iniciar el IP y esperar que termine. Igual que en un DMA. Código HLS #include "core.h" int setMem(unsigned char value, volatile unsigned char *addrMaster, int size) { #pragma HLS INTERFACE m_axi depth=200 port=addrMaster offset=slave bundle=MASTER_BUS #pragma HLS INTERFACE s_axilite port=size bundle=CRTL_BUS #pragma HLS INTERFACE s_axilite port=value bundle=CRTL_BUS #pragma HLS INTERFACE s_axilite port=return bundle=CRTL_BUS if (size < MAX_TRANSFER_SIZE) { for (int idxMemAddr = 0; idxMemAddr < size; idxMemAddr++) { addrMaster[idxMemAddr] = value; } return 0; } else { return -1; } } Master AXI Interface #pragma HLS INTERFACE m_axi depth=200 port=addrMaster offset=slave bundle=MASTER_BUS • El IP se comunicará directamente con la Memoria usando: – Un puerto M_AXI (MASTER_BUS) (addrMaster) – Un puerto S_AXILite para setear la dirección (esto es porque especificamos como SLAVE el offsset) – Otro puerto S_AXILite (CRTL_BUS) para otros parámetros: • size • Value • Return (Control:) Prototipo: core.h // Size limit // Maximum AXI4 full burst lenght is 256 bytes #define MAX_TRANSFER_SIZE 200 const int max_depth = MAX_TRANSFER_SIZE; int setMem(unsigned char value, volatile unsigned char *addrMaster, int size); Test para Simulación C #include <stdio.h> #include "core.h" unsigned char someMem[100]; int main() { setMem(55, someMem, 100); for (int idx = 0; idx < 100; idx++) { printf("Value someMem[%d]=%d\n",idx,someMem[idx]); } return 0; } Simulación Síntesis:Interfaces • Aquí vemos la interface AXILite para setear la dirección Síntesis: Interface • Aquí vemos la interface CRTL_BUS también de tipo AXI Lite para los dos parámetros: value y size. Síntesis: Interfaces M_AXI • Interface M_AXI Interfaces • Nuestro IP y sus interfaces Vivado Block Design Interconect: de PL a Memoria High Performance Ports • Se usan High Performance Ports que dan acceso a los controladores de Memoria Dinámica que se encuentran en el Zynq • Es necesario configurar su uso en el IP Zynq Direcciones de Memoria • En el IP, se ve la memoria DDR desde la dirección 0x00000000 hasta la 0x1FFFFFFF SDK: Aplicación (1) #include <stdio.h> #include <xparameters.h> #include <xsetmem.h> #include <xil_cache.h> #define SIZE_ARRAY 100 #define MEM_BASE_ADDR 0x00000000 #define TX_BUFFER_BASE (MEM_BASE_ADDR + 0x00A00000) unsigned char *someMem = (unsigned char *)TX_BUFFER_BASE ; // our object ip XSetmem doSetMem; XSetmem_Config *doSetMem_cfg; SDK: Aplicación (2) void initSetMem() { int status = 0; doSetMem_cfg=XSetmem_LookupConfig(XPAR_SETMEM_0_DEVICE_ID); if (doSetMem_cfg) { status= XSetmem_CfgInitialize(&doSetMem,doSetMem_cfg); if (status != XST_SUCCESS) { xil_printf (" Failed to Initialize \n"); } } } SDK: Aplicación (3) int main() { int error; int idx; initSetMem(); xil_printf ("Comenzando \n"); error=0; for ( idx =0; idx<SIZE_ARRAY; idx++) { someMem[idx]= 0; } SDK: Aplicación (4) // use the IP core // Configure the axi master to address 0x00300000, value 27 // and size 100 XSetmem_Set_addrMaster(&doSetMem, TX_BUFFER_BASE); XSetmem_Set_size(&doSetMem, SIZE_ARRAY); XSetmem_Set_value_r(&doSetMem, 27); // Start and wait Xil_DCacheFlush(); XSetmem_Start(&doSetMem); while (!XSetmem_IsDone(&doSetMem)); SDK: Aplicación (5) while (!XSetmem_IsDone(&doSetMem)); Xil_DCacheFlush(); error = XSetmem_Get_return(&doSetMem); xil_printf("Valor AXI Master result: %d\n",error); for (idx =0; idx<SIZE_ARRAY; idx++) { xil_printf ("Value somemem[%d] = %d\n", idx, someMem[idx]); } xil_printf("Test done\n"); return 0; } Debugging : antes de que ARM inicialice Debugging: antes de iniciar el IP Debugging: después de terminar IP ¡Gracias a Leonardo! • de Development Channel, youtube.