十二 · 2023年04月27日

Dispatcher By Round Robin

✎ 编 者 按 

基于RR的多路分发调用

》多路一出的场景

    在SpinalHDL代码中,StreamArbiter提供了完善的多入一出的调度机制。里面可能应用的较多的是Round Robin调度。在之前的文章《你知道如何做多端口仲裁么》中详细讲述了Round Robin调度思想。然而还有一类应用场景就是针对一入多出的情况:

image.png

    这其实也是之前微信群里面群友问的一个类似的场景。在一些应用里,来自上游的数据或者任务分发给多个Kernel来进行执行处理(如多个报文解析模块)。针对每个任务,其具体的执行时间会有差异(比如在网络报文头解析中,不同层协议所需要的时钟周期数并不相同)。那么为了尽可能避免Kernel空闲,显然如果采用简单的顺序分发至Kernel1~kerneln会存在潜在的Kernel空闲。比如(假定n=3):

  • Task1——>Kernel1;100 Clock Cycle
  • Task2——>Kernel2;50 Clock Cycle
  • Task3——>Kernel3;10 Clock Cycle
  • Task4——>Kernel1;10 Clock Cycle

    显然,这里如果将Task4分发至Kernel1将会导致Dispatcher的阻塞。那么针对这种场景,显然是下游Kernel谁空闲将任务分发给谁更合适。

》StreamFragmentRoundRobinDispatcher

    不同于StreamArbiter所针对的多入一出的谁有任务调度谁的RR调度,这里是一种一入多出的谁空闲任务给谁的RR调度,即Dispatcher By Round。如果你看过之前上面的文章,那么这里可以很容易做实现。考虑到真实的应用场景,这里仅针对Stream Fragment形式的调度实现:

image.png

    相比于StreamArbiter中采用多路输入信号的valid信号作为调度请求request相反,这里(Line:19)采用多路输出端口的ready信号作为roundRobin的request请求,从而实现谁空闲把任务给谁。

    如之前前文所说,Round Robin其实是一种优先级位置变化的最低优先级调度,故这里(Line:19)通过mask_locked的循环左移来实现优先级排序。故这里在初始化时将mask_locked的最高位初始化为1。

    这里采用mask_route来标识对应的端口仲裁结果。对于一帧Fragment Stream流,其首拍时由于仲裁结果还未锁定,故采用mask_arbited来充当仲裁标示,而在随后报文锁定后采用mask_locked来执行(确保一帧任务的调度不会被下游ready信号的变化所影响。如果下游端口能一帧完整报文之间不会拉低ready那么这里还可以进一步进行优化)。

    对于多Kernel处理结果需要保序输出的场景,这里提供了port_sel_oh信号来输出指示当前报文送至哪个端口。使用时可能需要再例化一个FIFO作为保序结果存储,此时在例化该模块连接port_in端口时可能需要一个continueWhen将保序Fifo的push.ready考虑进去。在port_in.firstFire时将port_sel_oh写入保序Fifo。        

☆ END ☆

作者:玉骐
原文链接:Spinal FPGA
微信公众号:
 title=

推荐阅读

更多SpinalHDL技术干货请关注Spinal FPGA欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。
推荐阅读
关注数
1581
内容数
133
用SpinalHDL提升生产力
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息