0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

队列管理电路-上篇

jf_78858299 来源:芯工阿文 作者:芯工阿文 2023-01-21 16:49 次阅读

在数字芯片设计中,几乎所有模块都会涉及到队列管理。输入输出的管理、不同数据流的调度、乱序数据的重排序、不同模块的同步处理、资源管理,等等,均会涉及到队列管理逻辑。如何选择合适的硬件逻辑,对模块的微架构有较大的影响,需要基于具体需求做综合权衡后再做选择。本文简单罗列几种队列管理逻辑,均是个人曾经实现过的。

1 最简单的队列-FIFO

First In First Out,用于输入输出之间的缓冲,吸收输入侧的突发流量。实现也比较简单,深度固定的环形buffer,使用读写指针进行管理。需要注意的是,读写指针的管理,FIFO为空和FIFO为满,读写指针均是相等的,需使用另外的标号进行处理。也有其余的实现方式,比如移位寄存器

图片

使用SpinalHDL实现FIFO的代码如下。输入输出的push/pop,使用了valid/ready握手的Stream接口;使用Mem定义环形buffer,pushPtr/popPtr分别对应读写指针;特别关注risingOccupancy信号,push和pop没有同时发生时,更新为push,该信号可用于标记FIFO的空满状态。读写指针相等且该信号为低,表示FIFO为空;读写指针相等且该信号为高,表示FIFO为满。

// spinal/lib/Stream.scala
val io = new Bundle {
val push = slave Stream (dataType)
val pop = master Stream (dataType)
val flush= in Bool() default(False)
val occupancy = out UInt (log2Up(depth + 1) bits)
val availability = out UInt (log2Up(depth + 1) bits)
}
val ram = Mem(dataType, depth)
val pushPtr = Counter(depth)
val popPtr = Counter(depth)
val ptrMatch = pushPtr === popPtr
val risingOccupancy = RegInit(False)
val pushing = io.push.fire
val popping = io.pop.fire
val empty = ptrMatch & !risingOccupancy
val full = ptrMatch & risingOccupancy

io.push.ready := !full
io.pop.valid := !empty & !(RegNext(popPtr.valueNext === pushPtr, False) & !full) //mem write to read propagation
io.pop.payload := ram.readSync(popPtr.valueNext)

when(pushing =/= popping) {
risingOccupancy := pushing
}
when(pushing) {
ram(pushPtr.value) := io.push.payload
pushPtr.increment()
}
when(popping) {
popPtr.increment()
}

2 共享Buffer的多队列FIFO

考虑一个场景,输入的请求需要分发至不同的输出侧,下游存在反压。简单实现,基于不同的输出分别设置FIFO,但可能存在资源浪费,某些数据流场景FIFO的利用率不高,尤其是在数据位宽较大的场景。

共享Buffer的多队列FIFO,每个队列的FIFO还是按照简单队列进行管理,基于每个队列管理读写指针。但是,不再使用环形Buffer,每个buffer entry记录其队列号、队列指针和Payload,如下图所示。对于Payload位宽较小的场景,收益不大,若存在大位宽时,可有效提升Buffer的利用率。

图片

将数据写入Buffer时,先找一个Free Entry(Vliad为低),将该数据所属的队列号及其对应的写指针、Payload写入到对应的Entry内。读取Buffer时,则使用队列号和读指针进行匹配,将命中的Entry内容读取出来。若读写指针所能描述的范围比buffer深度大,则不需要额外的标号记录空满状态。存在的问题,若buffer深度较大或队列数量较多,队列号和指针匹配逻辑会占用较多的资源。

3 重力FIFO

类似于排队,从队头开始寻找可输出的Entry,调度输出并留下空位,后面的Entry再往前排,新输入的请求则放置在队列尾。如图所示,存在有效数据的Entry,其前面的Entry被调度后留下空位,该Entry就像受到重力作用往下掉,因此我也称之为重力FIFO。

图片

该结构的问题,存在大量的移位,设想Payload位宽为32bit,深度为32,将近1kbit的寄存器在做移位处理,其功耗可想而知。但是对于一些具体场景,还是能够带来一些收益的,如队列数量较大,甚至大于buffer深度;至于Payload位宽较大的场景,可考虑二次索引处理,Payload保存至另外的buffer,该结构内的Payload Entry则缓存其索引信息

4 Bitmap排序

先来看一个结构,深度为8的队列,每个Entry使用8bit缓存8个Entry的状态,若该状态信号满足触发条件,如全为0,则调度该Entry内容。

Bitmap排序就是使用了这一结构,在输入请求进入队列后,检查当前队列状态,存在关联请求的Entry位置置位为1,否则为0。若存在请求输出之后,所有Entry状态的对应位置均设为0。若某个Entry的状态信号全为0,则请求调度输出。其数据结构如下图所示,其中0/1仅作为状态信号的示例,并非实际场景。

图片

该结构可以实现较为灵活的排序,队列的数量几乎不会受到限制,进入队列的请求,也可修改其Mask Bitmap,动态刷新其先后关系。与重力FIFO类似,无需额外的数据结构保存其队列关系,而是直接体现在原有结构内。存在的问题,队列深度会受到面积限制,面积与深度的平方成正比;另外,在动态更新Mask Bitmap之后,某些实现可能无法保证先后关系。

面积问题可以考虑用分级处理。如需实现256深度的队列,其Mask Bitmap需要65536个寄存器实现Mask Bitmap。分解为8个32深度的队列,需要的寄存器数量为8192;分解为16个16深度的队列,寄存器数量为4096。

5 小结

队列管理电路还有一个比较常见的实现,链表。在乱序数据的重排序、资源管理等等方面,通常会用链表实现,与上几个结构相比,链表会复杂一些。该部分将在下篇描述。

除最简单的FIFO之外,其余几个都没有代码,如各位要有兴趣,请留言,我可以再尝试写一些Spinal代码实现。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 芯片设计
    +关注

    关注

    15

    文章

    888

    浏览量

    54394
  • 队列管理
    +关注

    关注

    0

    文章

    4

    浏览量

    6264
  • 数字芯片
    +关注

    关注

    1

    文章

    99

    浏览量

    18241
收藏 人收藏

    评论

    相关推荐

    主动队列管理建模及最优控制策略

    主动队列管理建模及最优控制策略针对主动队列管理(AQM)研究中缺乏系统的理论分析的问题,引入最优控制理论进行分析,得到了主动队列管理的数学模型,该模型包括两个差分方程,分别描述队列长度
    发表于 06-14 00:14

    FreeRTOS学习笔记(六)——队列管理

    FreeRTOS学习笔记(六)——队列管理
    发表于 09-28 14:07

    FreeRTOS学习笔记(六)——队列管理

    FreeRTOS学习笔记(六)——队列管理
    发表于 10-21 20:40

    Agilent TCP和队列管理

    TCP和队列管理
    发表于 10-31 09:08

    简单罗列几种队列管理逻辑电路

    ,寄存器数量为4096。5 小结队列管理电路还有一个比较常见的实现,链表。在乱序数据的重排序、资源管理等等方面,通常会用链表实现,与上几个结构相比,链表会复杂一些。该部分将在下篇描述。除最简单的FIFO
    发表于 08-29 14:23

    什么是链表?怎样使用链表作为队列管理电路

    前文聊了队列管理的几种典型电路,硬件逻辑简单,代码实现时容易操作。链表也是队列管理的常用电路,相比前文的几种结构,会稍微复杂一些。1 什么是链表在非连续、非顺序的物理存储结构上,通过指
    发表于 08-29 14:26

    不同服务类型的队列管理及性能比较

    为提高网络利用率和数据包处理速度,针对不同应用的网络流量,在网络拓扑结构的参数设置相同的情况下,使用NS2模拟器对瓶颈链路分别采用7种主动队列管理机制进行仿真,通过
    发表于 04-09 09:46 11次下载

    一种改进的主动队列管理算法

    主动队列管理是实现网络拥塞控制的重要技术,但是多数主动队列管理算法如随机早期检(RED)都存在对参数依赖性强的问题。针对RED算法中平均队列长度不能完全反映网络拥塞状况的
    发表于 04-13 09:08 14次下载

    网络中常用的队列管理方法比较

    本文主要介绍了网络中常用的两种队列管理方法:先进先出(FIFO)和随机提前检测(RED),并且通过实验比较了这两种队列管理方法在解决网络拥塞控制方面的表现,体现了研究
    发表于 05-25 11:24 9次下载

    主动队列管理建模及最优控制策略

    针对主动队列管理(AQM)研究中缺乏系统的理论分析的问题,引入最优控制理论进行分析,得到了主动队列管理的数学模型,该模型包括两个差分方程,分别描述队列长度和平均队列
    发表于 05-25 21:44 17次下载

    一种基于速率的公平队列管理算法

    针对主动队列管理算法普遍存在的公平性问题,提出基于速率的公平队列管理算法RFED。该算法根据分组的到达速率调节丢包率,将队列的到达速率控制在链路的服务速率下,根据
    发表于 10-04 14:11 15次下载

    一种参数自适应的主动队列管理算法—自适应BLUE

    BLUE算法是一种典型的主动队列管理 (Active Queue Management,AQM) 算法,研究表明BLUE算法优于RED算法。BLUE算法使用丢包事件和链路空闲事件控制网络拥塞。但由于BLUE算法在参数设置方面
    发表于 11-24 14:19 10次下载

    面向网络能效优化的动态权重队列管理算法

    针对流量传输过程中能效优化的问题,提出一种面向网络能效优化的动态权重队列管理算法DW_WFQ。该算法在加权公平队列(WFQ)的基础上通过动态地分配各类业务流的权重,以更加灵活的方式分配各类业务
    发表于 12-20 09:27 0次下载
    面向网络能效优化的动态权重<b class='flag-5'>队列管理</b>算法

    传感器网络队列管理算法DQC

    为了在保证无线传感器网络时延要求的同时最小化功率消耗,提出一种基于占空比控制和时延保证的传感器网络队列管理算法(DQC)。该算法根据不断变化的网络条件,为了更好地控制节点占空比和队列阈值,采用一种
    发表于 01-10 17:13 0次下载

    队列管理电路-下篇

    前文聊了队列管理的几种典型电路,硬件逻辑简单,代码实现时容易操作。链表也是队列管理的常用电路,相比前文的几种结构,会稍微复杂一些。
    的头像 发表于 01-21 17:11 545次阅读
    <b class='flag-5'>队列管理</b><b class='flag-5'>电路</b>-下篇