Vivado HLS推动协议处理系统蓬勃发展(下)_第1页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、vivado hls推动协议处理系统蓬勃发展(下) 4 设置容易系统 协议处理普通状况下属于状态事务。必需先挨次读取在多个时钟周期内进入的数据包字,然后按照数据包的某些字段打算进一步操作。通常应对这种处理的办法是用法状态机,对数据包举行迭代运算,完成须要的处理。例3是一种容易的状态机,用于按照上一级的输入丢弃或转发数据包。该函数接收三个参数:一个是通过“indata”流接收到的输入分组数据;一个是通过“validbuffer”流显示数据包是否有效的1位旗标;第三个是称为“outdata”的输出分组数据流。注重vivado hls函数中的参数是按引用传递的。这在用法较为复杂的vivado hls

2、流的时候是须要的。ap_uint等较为容易的数据类型则可按值传递。第2行中的流水线编译命令指示vivado hls将该函数流水线化,让初始化间隔为1(ii=1),即每个时钟周期处理一个新的输入数据字。vivado hls负责核验设计,并确定需要在设计中引入多少个流水线级来满足调度限制要求。例3:用法vivado hls的有限状态机1 void dropper(stream& indata,stream& validbuffer,stream& outdata) 2 pragma hls pipeline ii=1 enable_flush34 static enum dstate d_idle

3、 = 0, d_stream, d_drop dropstate;5 axiword currword = 0, 0, 0, 0;67 switch(dropstate) 8 case d_idle:9 if (!validbuffer.empty() & !indata.empty() 10 ap_uint valid = validbuffer.read();11 indata.read(currword);12 if (valid) 13 outdata.write(currword);14 dropstate = d_stream;15 16 17 else18 dropstate =

4、 d_drop;19 break;20 case d_stream:21 if (!indata.empty() 22 indata.read(currword);23 outdata.write(currword);24 if (currword.last)25 dropstate = d_idle;26 27 break;28 case d_drop:29 if (!indata.empty() 30 indata.read(currword);31 if (currword.last)32 dropstate = d_idle;33 34 break;35 36 第4行用于声明一个静态枚

5、举变量,用于表达该fsm中的状态。用法枚举与否可以挑选,不过能让代码更简单阅读,由于可以给状态适当地命名。不过用法任何整数或ap_unit变量也能得到与之类似的结果。第5行用于声明一个“axiword”类型的变量,用于存储预备从输入中读取的分组数据。第7行中的开关语句用于表达实际的状态机。建议用法开关,但非强制要求。用法if-else决策树也能执行同样的功能。开关语句能够让vivado hls工具更高效地枚举全部状态,并优化得到的状态机rtl代码。执行从d_idle状态开头,此时fsm从第10行和第11行的两个输入流读取。这两行分离代表两种流对象读取办法。这两种办法均从设定的流读取,然后将结果

6、存储到给定变量中。这种办法实行堵塞式读取,意味着假如该办法调用无法挨次执行,就会暂停执行该函数调用中的其余代码。在试图读取空流的时候会发生这种状况。5 流分割和合并在协议处理中,按照协议栈特定字段转发数据包给不同模块,然后在发送前将不同的流重新组合,是一项关键功能。vivado hls允许用法高级架构来推进这一转发过程,详细如例4中所示的流合并。例4:容易的流合并状况1 void merge(stream indatanum_merge_streams, stream&outdata) 2 pragma hls inline off3 pragma hls pipeline ii=1 enab

7、le_flush45 static enum mstatem_idle = 0, m_streammergestate;6 static ap_uintrrctr = 0;7 static ap_uintstreamsource = 0;8 axiword inputword = 0, 0, 0, 0;910 switch(mergestate) 11 case m_idle:12 bool streamemptynum_merge_streams;13 pragma hls array_partition variable=stream-empty complete14 for (uint8

8、_t i=0;i15 streamempty = indata.empty();16 for (uint8_t i=0;i17 uint8_t tempctr = streamsource + 1 + i;18 if (tempctr = num_merge_streams)19 tempctr -= num_merge_streams;20 if(!streamemptytempctr) 21 streamsource = tempctr;22 inputword = indatastreamsource.read();23 outdata.write(inputword);24 if (i

9、nputword.last = 0)25 mergestate = m_stream;26 break;27 28 29 break;30 case m_stream:31 if (!indatastreamsource.empty() 32 indatastreamsource.read(inputword);33 outdata.write(inputword);34 if (inputword.last = 1)35 mergestate = m_idle;36 37 break;38 39 本例体现的是模块合并功能的用法,其中一个流阵列作为输入(indata),一个单流作为输出(out

10、data)。这个模块的功能是以无区分的方式从输入流读取数据,然后将读取的数据输出给输出流。该模块采纳双级fsm实现,其结构与前文介绍的结构全都。fsm的第一个状态用于确保挑选输入流的无区分性(fairness)。实现的办法是用法循环算法检查队列。该算法在完成上一队列的拜访之后,即从下一队列起查找新的数据。第17到19行的代码采纳的即是此循环算法。常量num_merge_streams用于设定待合并的流的数量。接下来的第20行负责测试当前的流,其内容用tempcntr变量标示。假如当前流非空,则将其设置为活跃流(第21行)。然后从该流中读取数据(第22行)。假如读取的数据字不是最后一个数据字(由

11、第24行负责检查),则状态机进入m_stream状态,然后输出来自该流的剩余数据字。在处理完成最后一个数据字后,fsm返回m_idle状态,然后重复上述过程。这个模块引入了一个新的编译命令,称为“array_partition”。该编译命令能让vivado hls了解为了提高吞吐量,是否需要把一个阵列拆分为多个子阵列。假如未加设定,vivado hls会用法双端口bram来拜访阵列。假如要在一个时钟周期中拜访阵列两次以上,假如不适当地提高初始化间隔(ii)的值,该工具将无法调度这些拜访。在本例中,略去array_partition编译命令,将nun_merge_streams值设为8,就可以让

12、ii=4。但由于想能够在每个时钟周期内拜访steamempty阵列的全部元素,让目标ii=1,我们需要对这个阵列举行充分分区。在本例中,该阵列实现为一组基于触发器的寄存器。拆分输入流的过程耳熟能详,把来自一个流的数据字正确地路由到一个流阵列即可。6 抽取字段和重新对齐字段在包处理中,抽取字段和重新对齐字段是最基本的操作之一。因为数据包普通是经过多个时钟周期内通过总线到达模块的,频繁的状况是需要的字段要么在它们抵达的数据字中未能对齐,要么簇拥在多个数据字中(往往两种状况都有)。因此要处理这些字段,必需将它们从数据流中抽取出来,存入缓存然后重新对齐以便处理。例5:源mac地址抽取示例1 if (!

13、indata.empty() 2 indata.read(currword);3 switch(wordcount) 4 case 0:5 mac_dst = currword.data.range(47, 0);6 mac_src.range(15, 0) = currword.data.range(63, 48);7 break;8 case 1:9 mac_src.range(47 ,16) = currword.data.range(31, 0);10 break;11 case 2:12 例5是一个十分容易的字段抽取和再对齐示例。这个示例从以太网报头中抽取源mac地址。数据通过称为“

14、indata”的64位流抵达。在每个时钟周期读入数据(第2行)。随后按照读取的数据字执行合适的语句。因此在第5行中源mac地址的头16位被抽取出来,并移位到mac_src变量的起始部分。在下一时钟周期中,mac地址的其余32位抵达总线,然后存入mac_src变量的32位更高位中。7 用多级层级创建系统上文研究了如何用法vivado hls实现容易的三级流水线。但是普通的包处理系统可能会包含分布在层级结构中多个层面的多个模块。图2即是这种系统的示例。在本例中,层级结构的第一层由两个模块组成,每个模块下面包括三个子模块。这个示例中的顶层模块与前面介绍的容易系统中顶层模块相像。但包含有三个子模块的较

15、低层模块用法inline编译命令来解析函数,将其子模块推送到顶层,如例6所示。例6:vivado hls中的中间模块1 void module2 (stream &indata,stream&outdata) 2 pragma hls inline34 因此在vivado hls完成综合后,系统基本3所示。这样vivado hls就能正确地按照这些模块创建数据流架构,完成模块的流水线化,然后同步执行。在嵌入该函数后,各模块和信号保持本来的名称不变。8 用法高级语言结构高层次综合的主要优势之一在于可以用法高级语言结构来表达复杂对象,与传统rtl设计相比,显著提高了抽象水平。下面的例子是描述一个小

16、型查找表。例7中的代码用于内容可寻址存储器(cam)类定义,它用法类对象创建一个表,供存储和复原上述原型系统的arp数据。该类有一个私有成员,这个私有成员是一个由“noofarptableentries”条“arptableentry”类型记录组成的阵列。这种类型属于一种数据结构,包括mac地址、对应的ip地址和用于解释该条记录是否包含有效数据的一个数位。例7:cam类定义1 class cam 2 private:3 arptableentry filterentriesnoofarptableentries;4 public:5 cam();6 bool write(arptableent

17、ry writeentry);7 bool clear(ap_uint clearaddress);8 arptableentry compare(ap_uintsearchaddress);9 ;这个类也包括四种在这个表上运算办法(其中一个是构造器)。其中的一个,即比较法,用于实现真正的查找功能。本例通过提供ip地址来返回相应的mac地址。处理的办法是用法“for”循环查找表中的每一条记录,搜寻有相同ip地址的有效记录。然后完整地返回这条记录。假如没有找到,就返回无效记录。为让设计实现ii=1的目标,必需彻低绽开这个循环。例8:用于cam类的比较法1 arptableentry cam:compare(ap_uint searchaddress)2 for (uint8_t i=0; i3 if (this-filterentries.valid = 1 &searchaddress = this-filterentries.ipaddress)4 return this-filterentries;5 6 arptableentry temp = 0, 0, 0;7 return temp;8 上述阅历和示例明确解释,用户可以用法vivado hls充分发挥高级编程结构的作用,用类似软件的办法描述包处理系统。采纳rtl是难以实现的。9 10gbps速率下的协议处

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论