[XILINX-ACAP] AI Engine Programming: Single core

ref:

https://www.xilinx.com/html_docs/xilinx2020_2/vitis_doc/yii1603912637443.html

https://www.xilinx.com/support/documentation/sw_manuals/xilinx2020_2/ug1079-ai-engine-kernel-coding.pdf

https://github.com/Xilinx/Vitis-Tutorials/tree/2021.2/AI_Engine_Development/Feature_Tutorials/07-AI-Engine-Floating-Point/MatMult

 

1. Overview

 [XILINX-ACAP] AI Engine Programming: Single core

[XILINX-ACAP] AI Engine Programming: Single core

 [XILINX-ACAP] AI Engine Programming: Single core

 

2. Intrinsics

https://www.xilinx.com/html_docs/xilinx2020_2/aiengine_intrinsics/intrinsics/index.html

[XILINX-ACAP] AI Engine Programming: Single core

 

 3. Dataflow

两级hierarchy(Data memory (DM)和 寄存器)。 这里假设DMA 已经把操作数搬到Data memory 中。 

[XILINX-ACAP] AI Engine Programming: Single core

 

  • 定义寄存器变量
v32int8 chess_storage(wr0) bufA;  
v8acc8 acc;
  •  DM <-> vector registers

假设声明了input_window_int8 A,output_window_int8 B,

可以直接用adf 定义好的函数。

window_read_v8(A);
window_writeincr(B, srs(acc, shift)) 

也可以直接用指针

int8_t*  i_ptr = (int8_t*)(A->ptr);
v32int8 x = *((v32int8 chess_storage(DM_bankA) *restrict)(i_ptr));
  • vector registers <-> vector registers
chess_copy();// 拷贝
upd()/concat();// 更新、拼接
acc = mul(XA, XB); // 进计算流水
  • accumulator 相关
out:
   srs();// 舍入到向量寄存器
   put_mcd(); // 推给下一个core的acc寄存器
in:
   mac();//  来自计算输出
   ups();// 向量寄存器直接移位
   get_scd();// 接收前core推送

 4. Synchronization(Locks)

对于Data Memory,  kernel code 和DMA都要对其进行读写,就需要同步操作,这里是用硬件锁来控制的。举一个不考虑ping-pong buffer的例子。

4.1 Kernel side

window 用来从软件角度描述一片Data Memory, 这个数据结构会有这片存储的起始地址,长度,绑定的Lock等信息。

kernel 侧是一个while(true) 的死循环,进去以后首先要申请操作数的读锁和结果的写锁,拿到锁以后开始kernel code处理,结束后释放锁。

v4int32 buf0[1];
v4int32 buf1[1];

#define LOCK_0 0
#define LOCK_1 1
#define FOR_WRITE 0
#define FOR_READ 1

int main(){
    input_window_pi = window_init(buf0, LOCK_0);
    output_window_po = window_init(buf1, LOCK_1);
    while(true){
          window_acquire(input_window_pi, FOR_READ);
          window_acquire(input_window_po, FOR_WRITE);

          kernel_func(input_window_pi, output_window_po);

          window_release(input_window_pi, FOR_WRITE);
          window_release(input_window_po, FOR_READ);
    }
    return 0;
}

锁的初始值是0, 当程序进到window_acquire 的时候,先检查输入window pi 的锁的值, 发现LOCK_0 的值是0, 而FOR_READ 需要锁的值是1,程序就在这个地方等待。

当DMA 将数据写入Data memory 后,会修改LOCK_0 的值为1, 标识可以读了,kernel 就继续向下执行。

4.2 DMA side

DMA 侧描述一片Data Memory的是buffer descriptor(BD), 一组硬件寄存器,6x32bits。应该包含以下字段: 起始地址,长度,读写Memory的寻址模式(连续读写,跳地址读写),Lock 等。 

和kernel侧类似,DMA 开始搬数前需要申请并获得锁,搬数完毕后释放锁。

 

上一篇:XDP


下一篇:《计算机网络:自顶向下方法(第八版)》课程笔记三:第2章 Computer Networking: a Top-Down Approach (8th ed.) : Core Lectures Note