corundum是一个基于fpga的开源nic原型平台,用于高达100gbps及更高的网络接口开发。
corundum平台包括一些用于实现实时,高线速操作的核心功能,包括:高性能数据路径,10g/25g/100g以太网mac,pcie gen3,自定义pcie dma引擎以及本机高精确的ieee 1588 ptp时间戳。
背景我们基于corundum这个灵活且强大的平台开发了一款网络加速器。如图所示,我们的设计(位于app黄色部分)需要和原生数据流量共用一套dma if和主机host进行通信。紫色数据路径为用于dma操作的自定义分段内存接口,连接着corundum的高性能dma引擎和分段存储器。
在我们的设计中,需要频繁的进行dma读写操作。dma操作大致有两种类型,一种是小数据包的dma,长度在16b-64b之间,内容为硬件和主机通信的描述符,存放于desc fetch和cpl write模块内的描述符分段存储器;一种是大数据包的dma,长度大于1kb,内容为传输数据,存放于app下的数据分段存储器。
我们的设计通过了大量仿真,确认开发设计功能无误,随后开始上板测试。
问题我们的pcie链路速率gen3 * 8,pcie理论带宽为64g。在上板时出现了很奇怪的现象。
每次测试发送小数量级的请求时(10万次),预估pcie带宽在35g~40g。此时测试就会发生问题,整个系统瘫痪。
定位进一步定位问题,主机和fpga还可以通过mmio进行寄存器访问,但是dma已经完全卡死。
在dma if下设置计数器用于统计dma read请求的个数和响应:
if( s_axis_read_desc_valid && s_axis_read_desc_ready ) begin dma_read_req_cnt <= dma_read_req_cnt + 1'b1;endif( m_axis_read_desc_status_valid ) begin dma_read_status_cnt dma_read_cycle_max_cnt,这样就可以触发到模块出错的时刻。调整dma_read_cycle_max_cnt触发条件,逐步逼近出错时刻。
if(m_axis_read_desc_status_valid)begin dma_read_cycle_cnt <= 32'b0;end else if(s_axis_read_desc_valid && s_axis_read_desc_ready)begin dma_read_cycle_cnt = 1'b1)begin dma_read_cycle_cnt <= dma_read_cycle_cnt + 1'b1;end else begin dma_read_cycle_cnt dma_read_cycle_max_cnt))begin dma_read_cycle_max_cnt <= dma_read_cycle_cnt;end else begin dma_read_cycle_max_cnt <= dma_read_cycle_max_cnt;end同时,在ila内抓取一些相关的重要信号:基本的握手信号和相关流控信号。
外加统计read tlp的请求数据长度累计和返回cpld的数据长度累计。
定位“案发现场”按照触发设置,终于在ila中捕获到“案发现场”。
某个时刻,握手信号rx_cpl_tlp_ready不再置1,但rx_cpl_tlp_valid还存在。表明dma引擎出现了问题,无法再接收返回的cpld报文。
也就是从此刻开始,dma read请求的个数在一直增加,但是dma read响应的个数却不再增长。
定位到了出错时刻,此时便可以对模块内的重点信号展开分析。
原因分析前文已经去除掉了面向host的种种因素,因此最有可能出问题的地方只能是面向用户的用于dma操作的自定义分段内存接口。
这里的分段内存接口是corundum独特的体系结构的一种,对于pcie上的高性能dma,corundum使用自定义分段存储器接口。该接口被分成最大512位的段,并且整体宽度是pcie硬ip内核的axi流接口宽度的两倍。例如,将pcie gen 3 x16与pcie硬核中的512位axi流接口一起使用的设计将使用1024位分段接口,该接口分成2个段,每个段512位。与使用单个axi接口相比,该接口提供了改进的“阻抗匹配”,从而消除了dma引擎中的对齐和互连逻辑中的仲裁,从而消除了背压,从而提高了pcie链路利用率。具体地说,该接口保证dma接口可以在每个时钟周期执行全宽度,未对齐的读取或写入。此外,使用简单的双端口ram(专用于在单个方向上移动的流量)消除了读写路径之间的争用。
在自定义分段内存接口中,使用ram_wr_cmd_sel路由和复用。基于单独的选择信号而不是通过地址解码进行路由的。此功能消除了分配地址的需要,并允许使用可参数化的互连组件,这些组件以最少的配置适当地路由操作。
output wire [ram_seg_count*ram_sel_width-1:0] ram_wr_cmd_sel,output wire [ram_seg_count*ram_seg_be_width-1:0] ram_wr_cmd_be,output wire [ram_seg_count*ram_seg_addr_width-1:0] ram_wr_cmd_addr,output wire [ram_seg_count*ram_seg_data_width-1:0] ram_wr_cmd_data,output wire [ram_seg_count-1:0] ram_wr_cmd_valid,input wire [ram_seg_count-1:0] ram_wr_cmd_ready,input wire [ram_seg_count-1:0] ram_wr_done,dma read引擎使用分段内存的写入接口,将获取的cpld数据写入分段存储器中。使用ram_wr_cmd_sel决定写入哪个分段存储器,使用ram_wr_cmd_addr决定写入分段存储器的地址,使用ram_wr_done判断写入操作完成。
同样为分段内存接口设置计数器,用于统计分段内存接口的写入和写入完成操作。
if(ram_wr_cmd_valid[0] && ram_wr_cmd_ready[0])begin dpram_wr_cmd_cnt0 <= dpram_wr_cmd_cnt0 + 1'b1;endif(ram_wr_cmd_valid[1] && ram_wr_cmd_ready[1])begin dpram_wr_cmd_cnt1 <= dpram_wr_cmd_cnt1 + 1'b1;end if(ram_wr_done[0])begin dpram_wr_done_cnt0 <= dpram_wr_done_cnt0 + 1'b1;endif(ram_wr_done[1])begin dpram_wr_done_cnt1 0x000 -> 0x5fd。
而这正是触发测试错误的条件 :两次mem rd tlp的cpld碰巧发生了交织,或者说发生了乱序。小数据包的cpld超越了部分大数据包的cpld,先一步通过pcie链路传送至硬件。这种完成报文之间的乱序恰巧是pcie协议所允许的,用于保证生产者/消费者模型的正确运转,防止死锁的发生。
如果完成报文与之前的完成报文的transaction id不同,该报文可以超越之前的完成报文;如果相同,则不能超越。这里恰巧是两个连续的不同dma read操作,transaction id的tag必不相同,所以乱序是会发生的。
在仿真中恢复案发现场在仿真中,将“案发时刻”前后的波形文件csv导入仿真环境,或者直接使用force-release强制激励即可恢复案发现场。
通过在仿真中检查,很快便定位到是最近一级的dma_mux模块出现了问题,它会在这种情况下丢弃1-2个ram_wr_done。这有可能是每个分段存储器的写入路径时延不同,导致done信号同时到达mux模块或者是mux模块因为被占用而无法处理某一个分段存储器的写入完成,导致done信号丢失。
修改bug随后询问了alex我的想法是否正确:
他表示编写mux时使用fifo和计数器来捕获所有的done脉冲信号,并按正确的顺序转发,但似乎存在一个bug。
随后也证明确实是dma_ram_demux_wr这个模块存在问题:
alex随后进行了bug修改。对输入dma_ram_demux_wr的完成的done信号加入双向确认机制,确保不会遗漏任何done信号。
将修改完的代码进行了仿真测试,随后也通过了fpga上板测试。
总结错误的触发条件: 两次mem rd tlp的cpld发生乱序。小数据包的cpld超越了部分大数据包的cpld,先一步通过pcie链路传送至硬件。
错误原因: dma_ram_demux_wr因为ram_wr_done输入拥塞而丢失了分段内存接口的写入完成信号ram_wr_done。
进一步分析: 为什么corundum跑到100g带宽下都不会出现此问题?
corundum下dma的自定义分段内存接口拓扑如图所示:
在corundum的架构下,dma if 到所有分段存储器的写入路径延迟是一致的,因此即使发生了cpld乱序,dma_ram_demux_wr也不会因为ram_wr_done输入拥塞而丢失done个数。
在我们的设计中,在app下仍会进行若干级的dma mux将dma引擎进一步复用。
这样就会导致存在两个分段存储器的写入路径延迟不一致,进一步导致在dma_ram_demux_wr写入完成接口处发生争用导致ram_wr_done丢失。
补充: 修改完此bug之后,每级dma_if_mux会引入一拍额外的时延(用于双向确认),因此会对dma引擎的性能造成一定影响。为消除此影响,可以将dma_if_pcie_rd模块下的参数status_fifo_addr_width和output_fifo_addr_width由5扩大为6,使用更多资源来抵消额外的时延影响。
三星进军 AR 智能眼镜领域
吉事励产品广泛应用于新能源汽车测试
台积电买下茂迪20%股权 跨足太阳能领域
寒武纪思元MLU云端智能加速卡在中国移动推出,助推AI业务发展
采用SO-500封装的高效率4kHz、5.8A降压型转换器
寻找开源100G NIC Corundum中的隐藏BUG
恩智浦推出深度可调光SSL2129A LED照明控制IC
负载传感器应用原理电路分析
锐高发布一款LED系统--TALEXXengine STARK INDI
耐能携手合作伙伴正式进军自动驾驶领域
新兴产业规划出炉:构建工业机器人体系提上议程
在内卷的洗地机市场,戴森又一次实现了逆势狂奔
Mobileye携手长城汽车推出高级驾驶辅助系统和自动驾驶解决方案
国内首条G11掩膜板项目开工 成都或成我国最大掩膜版制造基地
197亿美元!微软完成收购AI公司Nuance
幸好安卓7.0这锅没背,华为mate9卡顿原因官方华为watch
达林顿电路简介及应用
高通三星玩自主架构 ARM未来“钱”途如何?
Tcl在Vivado中的应用
英特尔和飞利浦共同加快AI医疗的进一步发展