HLS第二十八课(UG871,接口综合)
接口的返回值,入口参数,都是需要用pragma约束的。
首先来回顾一下接口。
a clock and reset have been added to the design:
ap_clk and ap_rst.
A block-level I/O protocol has been added to control the RTL design: ports
ap_start, ap_idle and ap_done, ap_ready.
The default block-level I/O protocol is called
ap_ctrl_hs.
另一个常用的选项是ap_ctrl_none。
When the interface protocol ap_ctrl_none is used, no block-level I/O protocols areadded to the design. The only ports are those for the clock, reset and the data ports.
+++++++++++++++++++++++++++++++++++
来看第一个例子。
int adders(int in1, int in2, int in3) {
#pragma HLS INTERFACE ap_ctrl_none port=return#pragma HLS INTERFACE ap_none port=in3
#pragma HLS INTERFACE ap_none port=in2
#pragma HLS INTERFACE ap_none port=in1int sum;sum = in1 + in2 + in3;return sum;}
ap_ctrl接口的作用是和其他模块握手,告诉其他模块当前模块的FSM的状态。
#pragma HLS INTERFACE ap_ctrl_none port=return
ap_ctrl接口,是约束到return上的。
再来看看port-level。
对于纯输入信号,常用的是ap_none。
ap_none is the default I/O protocol for these C arguments.
#pragma HLS INTERFACE ap_none port=in1
表示当FSM运行在start for input状态时,会从port拍入数据。
这里,参数是以形参实体变量形式给出的,在实现时,被实现为一个single direction的input port。
模块内部可以配置一个reg。
这个例子中,模块内例化了两个加法处理器,最后将结果传输到return。
++++++++++++++++++++++++++++++++++++++++
第二个例子
void adders_io(int in1, int in2, int *in_out1) {*in_out1 = in1 + in2 + *in_out1;
}
第三个参数是形参指针,也就是说,它具备双向inout的能力,
返回值return是void的,也就是说,return可以不提供data port。
对于in1和in2,它们仍然是纯形参实体变量,input port。
可以选择ap_none,则只有input data port,没有任何input handshake port。这是默认选项,所以可以不加约束也是一样的效果。
也可以选择ap_stable,它类似于ap_none,区别在于,被认为是一个正常操作期间是恒定的值,它不是在FSM的start for input 状态读取,而是在模块复位后,在input after rst状态读取的。
所以,如果要使ap_stable的值生效,需要reset模块。通常用于配置常数参数。
也可以选择ap_vld,由前级模块发出有效信号。
#pragma HLS INTERFACE ap_vld port=in1
如果想向前级传递确认信号,可以选择ap_ack,
#pragma HLS INTERFACE ap_ack port=in2
对于inout的形参指针,可以选择ap_hs,那么这个接口具有最完备的握手信号集,支持双向传输。
既有input lane 还有output lane,两套data port。
in_out_i, in_out_i_ap_vld, in_out_i_ack,
in_out_o, in_out_o_ap_vld, in_out_o_ack,
在本例中,可以看出,它作为inout在使用,所以它的ap_hs握手,会有一个ovld来指示输出有效数据。
#pragma HLS INTERFACE ap_hs port=in_out1
本例中,虽然return端口是void,但是ap_ctrl_hs是默认模式,所以仍然会有
ap_start, ap_idle and ap_done, ap_ready.
++++++++++++++++++++++++++++++++++++++
第三个例子。
void array_io (dout_t d_o[N], din_t d_i[N]) {int i, rem;// Store accumulated datastatic dacc_t acc[CHANNELS];dacc_t temp;// Accumulate each channelFor_Loop: for (i=0;i<N;i++) {rem=i%CHANNELS;temp = acc[rem] + d_i[i];acc[rem] = temp;d_o[i] = acc[rem];}
}
两个形参数组,也即形参指针。
模块内部定义了一个static array,这将被实现为BRAM。
数组是一个一维的向量,所以,需要在一个for循环里,对一维向量的每个元素进行逐个处理。
数组在HLS中,默认被实现为SPRAM。
所以,形参数组,被默认实现为RAM port,因为假设的是RAM存在于模块外部。
这时,默认使用的接口约束是ap_memory。
RAM port理论上是有 read channel和write channel的。
在本例中,d_o这个RAM port,只被用来write,所以,它的read channel被省去了。
只有d_o_d0,d_o_addr0,d_o_we0,d_o_ce0。
在本例中,d_i这个RAM_port,只被用来read,所以,它的write channel被省去了。
只有d_i_q0,d_i_addr0,d_i_ce0.
the rolled for-loop ensure only one data sample can be read (or written) at a time.
for循环默认被理解为一个顺序执行的FSM,如果要提高并行度,就需要UNROLL FOR LOOP。
#pragma HLS UNROLL
被UNROLL后,同时访问RAM的需求就来了,需要给RAM多增加访问端口。
给d_i端口添加资源约束,
#pragma HLS RESOURCE variable=d_i core=RAM_2P_BRAM
注意,这里给端口添加资源约束,并不是模块内将端口用此资源来实现,而是说,假定模块外部,连接到此端口上的资源类型。
有,
d_i_q0,d_i_addr0,d_i_ce0,
d_i_q1,d_i_addr1,d_i_ce1,
给d_o端口添加接口约束,
#pragma HLS INTERFACE ap_fifo port=d_o
这里,将d_o端口约束为ap_fifo,并不是模块内将端口用一个FIFO来实现,而是说,假定模块外部,连接到此端口上的,是一个FIFO,所以d_o需要呈现为一个ap_fifo接口。
d_o_din, d_o_write, d_o_full_n,
这里,说明一点,形参数组,本质上是形参指针,可以被实现为RAM接口,也可以实现为FIFO接口。
之前使用SPRAM时,II是66,使用了DPRAM时,II是33,II降了一半,
要想更大程度的降低II,还需要继续增大RAM的访问接口,
给d_o端口,继续添加约束,添加数组分割约束,
#pragma HLS ARRAY_PARTITION variable=d_o block factor=4 dim=1
这个约束,使得d_o端口,将被分割成多个子端口,每个子端口,都被实现为FIFO接口。
d_o_din0, d_o_write0, d_o_full_n0,
d_o_din1, d_o_write1, d_o_full_n1,
d_o_din2, d_o_write2, d_o_full_n2,
d_o_din3, d_o_write3, d_o_full_n3,
继续添加约束,
给d_i端口,添加数组分割约束,
#pragma HLS ARRAY_PARTITION variable=d_i block factor=2 dim=1
这个约束,使得d_o端口,将被分割成多个子端口,每个子端口,都被实现为DPRAM接口。
d_i_0_q0,d_i_0_addr0,d_i_0_ce0,
d_i_0_q1,d_i_0_addr1,d_i_0_ce1,
d_i_1_q0,d_i_1_addr0,d_i_1_ce0,
d_i_1_q1,d_i_1_addr1,d_i_1_ce1,
现在,II被降到了17,
如果还想最大程度的降低II,可以考虑complete模式的数组分割约束。
#pragma HLS ARRAY_PARTITION variable=d_o complete dim=1
#pragma HLS ARRAY_PARTITION variable=d_i complete dim=1
#pragma HLS ARRAY_PARTITION variable=acc complete dim=1
d_i被完全分割时,就需要去掉之前的资源约束了,删除RAM_2p_BRAM的资源约束。
通常也是不推荐使用资源约束的。
此时,II降低到了1。
注意,谨慎使用资源约束。
可以看到,综合后,d_o数组每个元素都有一套自己的FIFO接口。
注意,HLS在约束时,有两个概念,一个是variable,一个是port,在模块内部,大多数情况下,去识别variable,只有在top层的模块,会有从形参variable衍生出的同名的port,这些portname,最终会以端口prefix前缀的形式存在。
+++++++++++++++++++++++++++++++++++++++++
第四个例子。
void axi_interfaces (dout_t d_o[N], din_t d_i[N]) {int i, rem;// Store accumulated datastatic dacc_t acc[CHANNELS];// Accumulate each channelFor_Loop: for (i=0;i<N;i++) {rem=i%CHANNELS;acc[rem] = acc[rem] + d_i[i];d_o[i] = acc[rem];}
}
首先,这里面有for循环,为了提高效率,首先要将for循环UNROLL。
#pragma HLS UNROLL factor=8
展平成8倍面积。
Select a factor of 8 to partially unroll the for-loop. This is equivalent to re-writing the C code to execute eight copies of the loop-body in each iteration of the loop (where the new loop only executes for 4 iterations in total, not 32,now i+=8).
然后,为了增加访问接口,进行数组分割,
#pragma HLS ARRAY_PARTITION variable=d_o cyclic factor=8 dim=1
这个约束,将d_o形参数组,分割成8个子数组,这次是以cyclic交替形式分割的。这也是实现为stream的推荐分割方式。
然后,为d_o形参数组,约束接口形式。将d_o形参数组,对外的接口形式,约束为axis形式。
#pragma HLS INTERFACE axis register both port=d_o
同样的,为d_i增加数组分割约束和接口约束。
#pragma HLS ARRAY_PARTITION variable=d_i cyclic factor=8 dim=1
#pragma HLS INTERFACE axis register both port=d_i
When the report opens in the information pane, confirm both d_i and d_o are implemented as eight separate AXI4-Stream ports.
d_o_0_AXIS,d_o_1_AXIS,d_o_2_AXIS,d_o_3_AXIS,
d_o_4_AXIS,d_o_5_AXIS,d_o_6_AXIS,d_o_7_AXIS,
d_i_0_AXIS,d_i_1_AXIS,d_i_2_AXIS,d_i_3_AXIS,
d_i_4_AXIS,d_i_5_AXIS,d_i_6_AXIS,d_i_7_AXIS,
此时的II,降低为9,
为了进一步降低II,还要继续对for循环优化,
虽然UNROLL了循环体,使其平铺了8路处理机,但是处理机内部的,仍然是顺序执行的,
在第一个操作步处理完后,只能等待其他后续操作步处理完,并再一次调度到首个操作步时,才能再次接收输入。
这种情况下,可以使用pipeline优化for循环。
使用了流水线约束后,循环体处理机在被综合时,不再是被综合成一个顺序FSM,分别调度每个操作步,而是将每个操作步综合成独立的处理机,每个操作步拥有自己的FSM。操作步之间,通过握手及FIFO实现同步。
#pragma HLS PIPELINE rewind
指定II的目标是1,也可以不指定,因为默认II就是1.
rewind使得流水线连续向前运转。无间隔执行。
When the top-level of the design is a loop, you can use the pipeline rewind option.
when implemented in RTL, this loop runs continuously (with no end of function and function re-start cycles).
一般场合中,rewind并不常用。因为通常模块都需要re-start。
此时的II,降为4,
一次完整的数组输入,是32个数据,分为8个端口,共需要4次才能完整输入全部数据。
+++++++++++++++++++++++++++++++++++++++++
第五个例子。
void axi_interfaces (dout_t d_o[N], din_t d_i[N]) {int i, rem;// Store accumulated datastatic dacc_t acc[CHANNELS];// Accumulate each channelFor_Loop: for (i=0;i<N;i++) {rem=i%CHANNELS;acc[rem] = acc[rem] + d_i[i];d_o[i] = acc[rem];}
}
首先,这里面有for循环,为了提高效率,首先要将for循环UNROLL。
#pragma HLS UNROLL factor=8
展平成8倍面积。
Select a factor of 8 to partially unroll the for-loop. This is equivalent to re-writing the C code to execute eight copies of the loop-body in each iteration of the loop (where the new loop only executes for 4 iterations in total, not 32,now i+=8).
再使用pipeline优化for循环。
#pragma HLS PIPELINE rewind
然后,为了增加访问接口,进行数组分割,
#pragma HLS ARRAY_PARTITION variable=d_i cyclic factor=8 dim=1
#pragma HLS ARRAY_PARTITION variable=d_o cyclic factor=8 dim=1
将return的访问,以及ap_ctrl的访问,收纳到s_axi_lite总线中去,ap_ctrl和return,不再以IO端口的形式存在,而是位于s_axilite总线中的register。
#pragma HLS INTERFACE s_axilite port=return
HLS第二十八课(UG871,接口综合)相关推荐
- JAVA 基础 / 第二十八课:接口与继承 / 如何设计JAVA的接口?
2018-03-19 在设计LOL的时候,进攻类英雄有两种,一种是进行物理系攻击,一种是进行魔法系攻击.这时候,就可以使用接口来实现这个效果. 接口就像是一种约定,我们约定某些英雄是物理系英雄,那么 ...
- NeHe OpenGL第二十八课:贝塞尔曲面
NeHe OpenGL第二十八课:贝塞尔曲面 贝塞尔曲面: 这是一课关于数学运算的,没有别的内容了.来,有信心就看看它吧. 贝塞尔曲面 作者: David Nikdel ( ogapo@ithink. ...
- Java调用大数据接口,学习Hadoop第二十八课(java通过调用接口来操作HBase)
上节课我们一起简单学习了HBase的一些理论,这节课我们一起学习用java调HBase的接口来操作HBase. 我们首先建一个工程,这里我们还用原始的新建一个lib包.然后我们把下载的hbase-0. ...
- JAVA 基础 / 第二十九课:接口与继承 / JAVA中的对象转型
2018-03-19 一.明确引用类型与对象类型的概念 引用类型与对象类型的概念 在这个例子里,有一个对象 new ADHero(), 同时也有一个引用ad 对象是有类型的, 是ADHero 引用也是 ...
- 【问链财经-区块链基础知识系列】 第二十八课 区块链如何助力万亿规模的供应链金融蛋糕
编者按:我国经济已由高速增长阶段转向高质量发展阶段.赊销项下的账期占压给实体经济的发展带了很大的束缚,国家近两年来多次发文鼓励和推动应收账款融资的发展.但传统应收类供应链金融模式,如保理.应收账款质押 ...
- java 实现类转接口_JAVA 基础 / 第二十九课:接口与继承 / JAVA中的对象转型
2018-03-19 一.明确引用类型与对象类型的概念 引用类型与对象类型的概念 在这个例子里,有一个对象 new ADHero(), 同时也有一个引用ad 对象是有类型的, 是ADHero 引用也是 ...
- 第二十八课:focusin与focusout,submit,oninput事件的修复
focusin与focusout 这两个事件是IE的私有实现,能冒泡,它代表获得焦点或失去焦点的事件.现在只有Firefox不支持focusin,focusout事件.其实另外两个事件focus和bl ...
- 新版标准日本语中级_第二十八课
语法 1. いや,~:いや是否定的表达方式,与いいえ类似,但いや的语气轻微.也用于否定自己刚刚说出的话. いえ也一样,但いえ比较有礼貌,男女都可以使用,而いや多为男性使用.此外,除了否定还可以 ...
- JAVA 基础 / 第二十九课:接口与继承 / JAVA 重写方法和多态
2018-03-19 子类可以继承父类的对象方法.在继承后,重复提供该方法,就叫做方法的重写:又叫覆盖 override 1.父类Item 父类Item有一个方法,叫做effect package p ...
最新文章
- systemverilog硬件设计及建模_3D建模和渲染都吃什么硬件?设计师该如何选购电脑...
- python 修改文件名_Python 批量修改文件名
- 当你收到面试通知后,如下的准备可以大大提升面试成功率
- 华为服务器维护岗位,服务器日常维护工作
- 身份证被盗用申请信用卡,造成逾期被催收怎么办?
- 设计灵感|总有一款对话界面符合你的应用风格!
- [ES6系列-01]Class:面向对象的“新仇旧恨”
- 6自由度机械臂的建立
- 【02】Java进阶:17-单例设计模式、多例设计模式、枚举、工厂设计模式、Lombok
- 网站CDN加速是什么? 看完这篇你就明白了!
- 服务器网卡支持热插拔吗,HDMI接口能“热插拔”吗?这篇告诉你
- shader篇-渲染纹理
- 驱动器控制模式功能简介(CSP,CSV,CST等)
- python显示日历_Python 程序显示日历
- Java实现微信小程序校验图片是否含有违法违规内容
- BT结束,高宽带有何用?
- HTML+CSS期末大作业:电影网站设计——猫眼电影(9页)
- OpenStack Dashboard
- steam 平台 饥荒 联机版 Linux云服务器 搭建教程
- 浏览器加载解析渲染机制的全面解析