• Rocket


    https://mp.weixin.qq.com/s/yO_9Ec3S5-AosRVLpsBgOg

     
    简单介绍基于通道位置的队列(LanePositionedQueue)的实现。
     
     
    1. LanePositionedDecoupledIO
     
    包含多个lane的ReadyValid接口,其中:
    a. maxVliad & maxReady:valid和ready信号的数量;
    b. validBits1 & readyBits1:表示valid和ready的数量所需要的比特数;
    c. lanes:包含多少个数据通路;
    d. ready:允许输出数据的个数;
    e. valid:可以输出数据的个数;
    f. bits:我方要输出的数据:同时输出lanes个T类型的数据;
     
    相较于ReadyValidIO,有如下的区别:
    a. bits包含多个通道的数据;
    b. ready/valid有多个位;也就是说ready/valid不是一个标志位,而是一个值;
     
    2. LanePositionedQueueIO
     
    使用LanePositionedDecoupledIO数据传递接口的队列接口。
     
    其中:
    a. lanes:通道数;
    b. depth:队列深度,即队列中可以存放的元素的个数;
    c. laneBitsU:表示lanes的数量所需要使用的比特数;
    d. enq: 入队的接口;
     
    入口的宽度为lanes,即一次最多可以入lanes个元素,即maxValid = lanes;而最多可以入队depth个元素,即maxReady = depth;
     
    e. deq:出队的接口;
     
    出口的宽度为lanes,即一次最多可以出lanes个元素,即maxReady = lanes;而最多可以出队depth个元素,即maxValid = depth;
     
    f. enq_0_lane:没有使用,略;
    g. deq_0_lane:没有使用,略;
     
    3. LanePositionedQueueModule
     
     
    4. LanePositionedQueue
     
     
    5. LanePositionedQueueBase
     
    基于通道位置的队列基本实现。因为是基本实现,不能直接使用,所以应该是抽象的:
    其实现类似于表格,把每个元素置于对应的行(row)列(lane)。
     
    1) io
     
    通道数为lanes;队列深度为rows * lanes,即每行lanes个元素,总共有rows行。
     
    2) capacity:容量,可以存放的元素的个数,即:rows * lanes;
    3) rowBits: 表示行号所需要的比特数;
    3) laneBits:表示通道号所需要的比特数;
    4) laneBits1:没有被使用,忽略;
    5) lane()
     
    计算向后移动add个元素之后,下一个lane的编号,以及是否发生了换行;
     
    a. 入队
     
    入队io.enq.valid个元素,enq_lane表示入队之后下一个lane的编号,enq_wrap表示是否发生了反转即换行。
     
    b. 出队
     
    出队io.deq.ready个元素,deq_lane表示出队之后下一个lane的编号,deq_wrap表示是否发生了换行。
     
    6) row()
     
     
    根据是否发生了换行,计算入队之后,当前行号以及下一行的行号。
     
     
    a. 入队
     
    当前行号:enq_row,下一行的行号:enq_row1;
     
    b. 出队
     
    当前行号:deq_row,下一行的行号:deq_row1;
     
    7) delta
     
    入队的元素个数与出队的元素个数的差值:
     
    这是一个有符号数,也就是说可以为负值。
     
    8) used & free
     
    队列(表格)中已有的和空闲的单元格的个数。
     
    9) position
     
    a. enq_pos:入队单元格的序号;
    b. deq_pos:出队单元格的序号;
    c. diff_pos:enq_pos和deq_pos之间的单元格数;
    d. 已用的和空闲的单元格数量之和为队列容量:assert(used + free === capacity.U)
    e. used == diff_pos,或者队列满:assert(used === diff_pos || (diff_pos === 0.U && used === capacity.U))
     
    10) io.enq.ready & io.deq.valid
     
    不考虑pipe和flow:
    io.enq.ready表示允许入队的元素的数量,io.deq.valid表示允许出队的元素的数量;
     
    断言:
    a. 入队数量不超过允许入队的数量:assert(io.enq.valid <= io.enq.ready)
    b. 出队的数量不超过允许出队的数量:assert(io.deq.ready <= io.deq.valid)
    c. 入队的数量不超过lanes:assert(io.enq.valid <= lanes.U)
    d. 出队的数量不超过lanes:assert(io.deq.ready <= lanes.U)
     
    11) enq mask
     
    vmask指valid对应的mask,rmask指ready对应的mask,lmask指lane对应的mask。
     
    a. UIntToOH1(x, width):生成一个宽度为width的mask,低x位为1,其余的高位为0;
    b. 2 * lanes:生成一个宽度为2*lanes的mask。意义:本行和下一行总共两行的mask。
    c. +& enq_lane:低enq_lane位为1,在vmask/lmask/lmask中皆是如此;
    d. io.enq.valid +& enq_lane:原有的元素所在的单元格,以及新入队元素对应的单元格,所对应的mask位都置为1;
    e. io.enq.ready +& enq_lane:原有的元素所在的单元格,以及后续io.enq.ready个未使用的单元格,所对应的mask位都置为1,截取其中的低2*lanes位;
    f. vmask & rmask:为1的mask位包含两部分:(enq_lane, 0],(io.enq.valid + enq_lane, enq_lane];
    g. & (~lmask):把位(enq_lane, 0]置0;
     
     
    撇开最后会被清零的位段(enq_lane,0],其余部分的意义如下:
    a. enq_vmask:本次入队io.enq.valid个元素所在单元格对应的位
    b. enq_rmask:当前行及下一行空闲单元格对应的位;
    c. enq_lmask:当前行中已有元素对应的位;
    d. enq_mask:本次入队io.enq.valid个元素所在单元格对应的位;
     
    PS. 因为断言:assert(io.enq.valid <= io.enq.ready),所以vmask中的位少于rmask中的位。在计算enq_mask时,是否仍有必要使用vmask & rmask?
     
    12) deq mask:参考enq mask;
     
     
    13) deq_bits
     
    输出到io.deq.bits,但是输入没有实现。这也是LanePositionedQueueBase需要标记为抽象类的原因之一。
     
    14) maybe_empty
     
    可能为空,并不一定为空。
    a. 当入队换行和出队换行中只有一个发生时,更新maybe_full的值;
    b. 因为入队换行和出队换行每次只换一行,所以当两个同时发生时,maybe_full的值不变;
    c. 当入队没换行,出队发生换行时,maybe_full为真;
    d. 当入队换行,出队没换行时,maybe_full为假;
     
    总结一下:当出队追上入队所在的行时,可能为空。
     
    15) bypass
     
    从deq_lane开始的lanes个单元格,如果是空闲的(!set),则直接把所对应的通道(i)上io.enq.bits(i)的值,透传给io.deq.bits(i)。
     
    a. row0:入队行与出队行相同,并且是出队行追上入对行;
     
     
    b. row1:入队行 = 出队行 + 1;
     
     
    c. !row0 && !row1:入对行与出队行之间隔了一个或者多个行;
     
     
    d. deq_lmask中:(deq_lane, 0]为1,(2*lanes, deq_lane]为1;
     
    e. 从deq_lane开始的lanes个单元格是否空闲,还是容易推导的,这里不再表述;
     
     
    6. FloppedLanePositionedQueueModule
     
    继承自LanePositionedQueueBase的可实例化的队列实现。
    把队列内存分成两个bank:
     
    分别从各自的bank中输出:
     
    分别向各自的bank中写入:
     
    7. FloppedLanePositionedQueue
     
    简化创建FloppedLanePositionedQueue的方法。
     
    8. OnePortLanePositionedQueueModule
     
    因为没有使用,这里不做略去不做介绍。
     
    9. 附录
     
  • 相关阅读:
    java线程池源码阅读
    websocketcometd源码阅读基于注解初始化(三)
    websocketcometd源码阅读与spring整合初始化(四)
    cometd源码阅读初始化(二)
    cometd源码阅读WebSocketTransport普通消息处理过程(八)
    websocketcometd源码阅读transport(五)
    一.安装软件
    GitHub一篇文章系列
    JavaJVM调优jstack找出最耗cpu的线程&定位问题代码
    Git总目录
  • 原文地址:https://www.cnblogs.com/wjcdx/p/10940742.html
Copyright © 2020-2023  润新知