HLS_ug871笔记

July 23, 2016
作者:dengshuai_super
出处:http://blog.csdn.net/dengshuai_super/article/details/52004095
声明:转载请注明作者及出处。


来源:

Chapter 10:Using HLS IP in a Zynq AP Soc Design

Lab 1: Implement Vivado HLS IP on a Zynq Device

这个实验练习集成了HLS IP 和(被HLS创建用来控制“实现在Zynq设备上的”设计的IP的)软件驱动程序。

Step 4:Creating an IP Integrator Block Design of the System

(1)Create Block Design
(2)Add IP(ZYNQ7 Processing System)
(3)双击IP,Presets—>选择板子型号
(4)MIO Configuration—> Application Processor Unit—->取消对Timer 0的选择(被选择的定时器都被取消)
(5)Interrupts—->Fabric Interrupts—->选择IRQ_F2P[15:0]—->OK
(6)单击Run Block Automation—>确认processing_system7_0被选择—->确认Apply Board Presets没被选择(如果选择了,它将重新应用我们第4步取消的定时器,造成Zynq设计块中有额外的端口)
(7)Add HLS IP
(8)单击Run Connection Automation(自动连线)
(9)选择S_AXI_HLS_MACC_PERIPH_BUS—>单击OK
(10)连接hls_macc_0的中断引脚interrupt(光标变成铅笔形状) 到PS7(processing_system7_0)上的IRQ_F2P[0:0]端口。
(11)选择Address Editor选项卡,确认hls_macc_0周围都有一个主地址范围。如果没有,点击Auto Assign Address。
(12)单击Validate Design图标,验证设计。
(13)在成功验证后,保存块设计。


Step 5: Implementing the System

在进行系统设计之前,你必须生成执行源(implementation sources)并创建一个HDL包装器作为合成和实现的顶层模块。
(1)返回到Project Manager窗口。
(2)右键Design Sources下的Zynq_Design(.bd对象)—>Generate Output Products
(3)Generate
(4)右键Design Sources下的Zynq_Design(.bd对象)—>Create HDL Wrapper—>OK
设计源文件树的顶层变为Zynq_Design_wrapper.v 文件。设计现在准备被综合,实现并且生成一个FPGA 编程比特流(FPGA progamming bitstream)。
(5)点击Generate Bitstream —> Yes
(6)Open Implemented Design —->OK


Step 6 : Developing Software and Running it on the ZYNQ System

你现在准备导出设计到Xilinux SDK。在SDK ,你创建运行在ZC702板子(如果有)上的软件。在HLS 导出Vivado IP Catalog package的期间生成这个HLS 块的驱动。为了让PS7软件可以和这个块通信,在SDK中必须提供这个驱动

(1)Vivado File menu 选择Export—>Export Hardward
(2)保证Include Bitstream 这个选项被选—>点击OK。
(3)Vivado File menu 选择Launch SDK。
(4)OK
(5)SDK 选择File–>New—>Application Project—>name:Zynq_Design_Test—>Next—>Hello World—>Finish
(6)给ZC702上电,并且测试这个HelloWolld程序,确保板子所有的连接允许你往FPGA设备上下载比特流。
(7)单击Xilinx Tools—>Program FPGA(or toolrar icon)
(8)Setup a Terminal in the Tab at bottom of workspace。(底部工具栏挨着Console,叫Terminal 1)
点击Connect图标—->选择Connection Type —>Serial—>选择USB串口线连接的端口(windows上可以打开设备管理器查看)—>波特率改为115200—>OK(也可以在右键应用程序项目Zynq_Design_Test—>Run as—>Run Configurations设置)
(9)在浏览窗格,右键应用程序项目Zynq_Design_Test—>Run as—>Launch on Hardware—>切换到Terminal标签—>确认Hello World接收到了。


Step 7 : Modify software to communicate with HLS block

这个完全修改好的源文件在教程文件的arm_code目录中。(将HelloWorld.c改为下面)

 #include 
#include "platform.h"
// Add BSP header files
#include   // Standard C functions, e.g. exit()
#include  // Provides a Boolean data type for ANSI/ISO-C
#include "xparameters.h" // Parameter definitions for processor periperals
#include "xscugic.h"     // Processor interrupt controller device driver
#include "XHls_macc.h"   // Device driver for HLS HW block

// HLS macc HW instance
XHls_macc HlsMacc;
//Interrupt Controller Instance
XScuGic ScuGic;
// Global variable definitions - used by ISR
volatile static int RunHlsMacc = 0;
volatile static int ResultAvailHlsMacc = 0;

// Setup and helper functions
int setup_interrupt();
int hls_macc_init(XHls_macc *hls_maccPtr);
void hls_macc_start(void *InstancePtr);
// The ISR prototype
void hls_macc_isr(void *InstancePtr);
// Software model of HLS hardware
void sw_macc(int a, int b, int *accum, bool accum_clr);

int main()
{
   print("Program to test communication with HLS MACC block in PL\n\r");
   int a = 2, b = 21;
   int res_hw;
   int res_sw;
   int i;
   int status;

   //Setup the matrix mult
   status = hls_macc_init(&HlsMacc);
   if(status != XST_SUCCESS){
      print("HLS peripheral setup failed\n\r");
      exit(-1);
   }
   //Setup the interrupt
   status = setup_interrupt();
   if(status != XST_SUCCESS){
      print("Interrupt setup failed\n\r");
      exit(-1);
   }

   //set the input parameters of the HLS block
   XHls_macc_SetA(&HlsMacc, a);
   XHls_macc_SetB(&HlsMacc, b);
   XHls_macc_SetAccum_clr(&HlsMacc, 1);

   if (XHls_macc_IsReady(&HlsMacc))
      print("HLS peripheral is ready.  Starting... ");
   else {
      print("!!! HLS peripheral is not ready! Exiting...\n\r");
      exit(-1);
   }

   if (0) { // use interrupt
      hls_macc_start(&HlsMacc);
      while(!ResultAvailHlsMacc)
         ; // spin
      res_hw = XHls_macc_GetAccum(&HlsMacc);
      print("Interrupt received from HLS HW.\n\r");
   } else { // Simple non-interrupt driven test
      XHls_macc_Start(&HlsMacc);
      do {
         res_hw = XHls_macc_GetAccum(&HlsMacc);
      } while (!XHls_macc_IsReady(&HlsMacc));
      print("Detected HLS peripheral complete. Result received.\n\r");
   }

   //call the software version of the function
   sw_macc(a, b, &res_sw, false);

   printf("Result from HW: %d; Result from SW: %d\n\r", res_hw, res_sw);
   if (res_hw == res_sw) {
      print("*** Results match ***\n\r");
      status = 0;
   }
   else {
      print("!!! MISMATCH !!!\n\r");
      status = -1;
   }

   cleanup_platform();
   return status;
}

void sw_macc(int a, int b, int *accum, bool accum_clr)
{
   static int accum_reg = 0;
   if (accum_clr)
      accum_reg = 0;
   accum_reg += a * b;
   *accum = accum_reg;
}

int hls_macc_init(XHls_macc *hls_maccPtr)
{
   XHls_macc_Config *cfgPtr;
   int status;

   cfgPtr = XHls_macc_LookupConfig(XPAR_XHLS_MACC_0_DEVICE_ID);
   if (!cfgPtr) {
      print("ERROR: Lookup of acclerator configuration failed.\n\r");
      return XST_FAILURE;
   }
   status = XHls_macc_CfgInitialize(hls_maccPtr, cfgPtr);
   if (status != XST_SUCCESS) {
      print("ERROR: Could not initialize accelerator.\n\r");
      return XST_FAILURE;
   }
   return status;
}

void hls_macc_start(void *InstancePtr){
   XHls_macc *pAccelerator = (XHls_macc *)InstancePtr;
   XHls_macc_InterruptEnable(pAccelerator,1);
   XHls_macc_InterruptGlobalEnable(pAccelerator);
   XHls_macc_Start(pAccelerator);
}

void hls_macc_isr(void *InstancePtr){
   XHls_macc *pAccelerator = (XHls_macc *)InstancePtr;

   //Disable the global interrupt
   XHls_macc_InterruptGlobalDisable(pAccelerator);
   //Disable the local interrupt
   XHls_macc_InterruptDisable(pAccelerator,0xffffffff);

   // clear the local interrupt
   XHls_macc_InterruptClear(pAccelerator,1);

   ResultAvailHlsMacc = 1;
   // restart the core if it should run again
   if(RunHlsMacc){
      hls_macc_start(pAccelerator);
   }
}

int setup_interrupt()
{
   //This functions sets up the interrupt on the ARM
   int result;
   XScuGic_Config *pCfg = XScuGic_LookupConfig(XPAR_SCUGIC_SINGLE_DEVICE_ID);
   if (pCfg == NULL){
      print("Interrupt Configuration Lookup Failed\n\r");
      return XST_FAILURE;
   }
   result = XScuGic_CfgInitialize(&ScuGic,pCfg,pCfg->CpuBaseAddress);
   if(result != XST_SUCCESS){
      return result;
   }
   // self test
   result = XScuGic_SelfTest(&ScuGic);
   if(result != XST_SUCCESS){
      return result;
   }
   // Initialize the exception handler
   Xil_ExceptionInit();
   // Register the exception handler
   //print("Register the exception handler\n\r");
   Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&ScuGic);
   //Enable the exception handler
   Xil_ExceptionEnable();
   // Connect the Adder ISR to the exception table
   //print("Connect the Adder ISR to the Exception handler table\n\r");
   result = XScuGic_Connect(&ScuGic,XPAR_FABRIC_HLS_MACC_0_INTERRUPT_INTR,(Xil_InterruptHandler)hls_macc_isr,&HlsMacc);
   if(result != XST_SUCCESS){
      return result;
   }
   //print("Enable the Adder ISR\n\r");
   XScuGic_Enable(&ScuGic,XPAR_FABRIC_HLS_MACC_0_INTERRUPT_INTR);
   return XST_SUCCESS;
}

Lab 2 : Streaming Data Between the Zynq CPU and HLS Accelerator Blocks

该实验演示了一种常见的高性能连接方案,用于连接(以流的方式消耗来源于CPU内存数据或者产生以CPU内存为目的地的数据的)硬件加速器模块。

本教程使用和“Using HLS IP in IP Intergrator”Lab1中相同的HLS和XFFT IP模块。在这个实验中,这些模块通过AXI DMA IP Core 连接到Zynq7 Processing System上的HP0 Slave AXI4 port。

硬件加速器模块是自由运行的,不需要驱动程序;只要数据被推进CPU或者从CPU被推出(通常简单的称为处理系统或者PS)。
这个实验强调软件需要避免高速缓存一致性问题。(avoid cache coherency issues)

你可能感兴趣的:(HLS+Opencv)