UG871 Reading Notes(3)

Chapter4 Interface Synthesis(接口综合)
接口综合是向设计中添加RTL端口的过程,这个过程不仅仅添加了物理意义上的端口,也顺带实现了相应的协议,使得此端口的数据传输自动同步化和优化。

一、 块级I/O控制协议
1.块级协议使得RTL Design可以被除数据端口之外的附加端口控制,这是块级I/O控制协议的本质作用。块级I/O协议只和函数本身(也就是说在插入directive时选中的是函数体本身)有关,而与数据端口无关。无特别说明时:块级I/O控制协议采用ap_ctrl_hs(short for all programmable control handshake)协议,以下是它包含的各个信号的含义:
首先约定一个术语:事务(Transaction):它指的是C语言函数完整执行一次的过程(也就是设计的RTL模块完整执行一次的过程)。

  1. ap_start:此信号用来控制块的运行,将此信号置为1从而启动块的运行。
    在ap_ready信号没有变成1之前,ap_start应该保持为高电平1,当ap_ready信号变成1之后,此时可以决定是将ap_start拉高进而继续执行下一次事务还是将ap_start拉低从而在此次事务结束时暂停执行。

  2. ap_ready:此信号表示此设计是否已经准备好读取下一次的输入数据,为1表示可以读入新的输入数据(也即表示此当前事务读取数据的任务以及全部完成,可以读入下一次事务的数据了)
    这个概念和流水线是密不可分的,如果当前设计不含流水线,那么下一次事务的数据读入显然要在下一次事务开始时再做。
    这个信号是用来判断何时要将下一轮的输入数据提供给输入端口的,而是否要开始下一轮的事务还得靠ap_start来操作。如果ap_start信号没有被置为高电平(也就是在当前事务结束时暂停执行),那么ap_ready将在当前事务执行完成之后自动变为低电平。

  3. ap_done:此信号表明的是当前事务是否已完成运行,为1表示当前事务的所有操作已经执行完毕,同时也表明ap_return
    输出的数据是有效(valid)的,在此之前ap_return端口输出的结果不保证是正确的,
    (但注意ap_return不是每个设计都有的端口)

  4. ap_idle:此信号表明当前设计是否正在工作,1表示工作已经完成且没有更多要执行的操作(也就是空闲态有效),0表示当前设计正在工作。

2.改变块级I/O控制协议,要在函数体本身来进行,可选择的块级I/O控制协议有如下几种:

  1. ap_ctrl_none:无块级I/O控制协议

  2. ap_ctrl_hs(block-level I/O control handshake protocal):这个上面已经介绍过

  3. ap_ctrl_chain(block-level I/O protocal for control chaining):此协议主要用来将流水块连锁(?)在一起,它和hs协议很相似,但是多了一个输入信号ap_continue,它要求ap_done和ap_continue均为1时才可以执行下一次事务,这给了流水线中处于后端的模块发起一个back-pressure的能力,也就是当其不能(也就是处理速度跟不上的时候)连续的获取新的数据时暂停前段流水运行。

  4. s_axilite(AXI-slave lite interface):用于在ap_ctrl_hs和ap_ctrl_chain之外的情境下,在块级I/O控制协议下,将分离的几个I/O端口实现为一个AXI Slave Lite接口的情形。

3.块级I/O控制协议的相连端口是return,这是个标识符,表示块级,而非返回值。事实上,即使是没有返回值的函数也可以使用return来表示指定块级控制协议。

4.使用ap_ctrl_none协议时,只剩下了clock、reset和数据端口,没有了ap_done信号,也就无法判断何时此块输出的数据是有效的了。事实上,C/RTL协同仿真需要块级I/O协议来序列化test_bench,所以有些情况下使用ap_ctrl_none时协同仿真会无法进行。

5.补记:当一个设计需要多于一个周期完成时,HLS会在综合时为它添加ap_clk和ap_rst,均为一个比特位的输入信号,表明这不是一个组合逻辑。

二、端口I/O协议
1.可以分配给端口的I/O协议受限于它的参数类型,并不是随心所欲的。
例如,传值调用和传引用调用可以分配的端口I/O协议是不同的:

在这里插入图片描述
端口I/O协议被综合成的不同类型
做一个小注解:ap_ack升高表示此数据被读取(捕捉),ap_vld升高表示此数据可以被读取(捕捉)

三、将数组实现为RTL接口
1.将数组参数实现为RAM(ap_memory)ports是HLS的默认操作,对于需要读写双重要求的数组参数,一般实现为一个双端口RAM(dual-port RAM Interface)。
关于单端口、伪双端口、真双端口的区别和联系的说明博客如下:
单端口、伪双端口、真双端口的区别和联系

2.就算指定为双端口实现,但是HLS认为这次设计中无需双端口,那么它也会实现为单端口RAM,实现双端口读写的一个重要方法是循环展开(pragma UNROLL),比如将循环展开为两块,这时就有了两个完全并行的处理逻辑,可以接受多个端口输入,HLS也会自动将端口综合为双端口,进而大幅提升了吞吐率。

3.想要在2的基础上进一步提升吞吐率,可以考虑采取数组划分(pragma ARRAY_PARTITION block)的优化方式。粗粒度下,可以采用BLOCK + 指定FACTOR的形式划分,也就是将数组按照维度划分成各自独立的FACTOR块,每一块启动一个独立端口去读写,这样也大幅提升了吞吐率。在本实验的例子中,输入数组划分为2块,被综合成2个独立的双端口RAM;输出数组被分成4块,被综合成4个独立的FIFO。

4.想要在3的基础上进一步提升吞吐率,可以考虑数组全划分(pragma ARRAY_PARTITION complete),这就相当于把一整个数组完全切分为一个个小寄存器(Register)了,自然的,被完全划分之后也不能被分配给一整块BRAM了,也就不能被综合成RAM,但这样的吞吐率是最高的。

5.以上从2-4,设计的吞吐率越来越高,相应花费的片上资源也会相应增加,但它不是一个线性关系,只是一个弱的正相关,资源和吞吐率由设计者来做权衡。

四、实现AXI4端口
1.当函数的顶层设计是一个单一循环时,流水化此循环时可以启动rewind选项。这将重复执行此循环,而不需要执行退出和重新进入函数的额外操作。

2.给设计的块级I/O添加一个AXI4-lite来实现CPU对设计的控制

猜你喜欢

转载自blog.csdn.net/zzy980511/article/details/111187266