1.面向对象
本文主要介绍握手的基本概念,读者可通过该篇文章对握手有个基本概念。也借此机会发表下自己对流水线中的握手反压的一些愚见。更深的理解可期待后续更新;
2. 握手简介
举个简单例子;
上图中sender拉高vld发送有效的数据给receiver,receiver拉高ready代表准备好接收数据。
- vld==1、ready==1:sender发送有效数据,receiver同时也准备好接收数据,完成一次有效数据传输;
- vld==1、ready==0:sender发送有效数据,receiver未准备好接收数据。反压sender,通常情况下sender需保持vld直到receiver拉高ready,完成一次传输;
- vld==0、ready==1:send没有数据需要发送,receiver已提前做好接收数据的准备;一旦send发起数据传输,即可完成一次握手;
- vld==0、ready==0:send没有数据需要传输,receiver也没有做好接收数据准备;
其实拿流水线的下级和上级很好理解,握手就体现了上下级之间的配合关系,使得流水能够正常运转;
握手与反压
握手的主要工作就是确保上下级之间的流量基本一致。关于反压可以有如下理解:
- 流水线上若上级处理速度大于下级处理速度,则下级需反馈信息给上级,我接收不过来你的数据了;即拉低ready;
- 流水线上若下级处理速度大于上级处理速度,则上级需反馈信息给下级,我处理速度跟不上你处理速度,给你的数据没那么快。即通过拉低一段时间的vld,使得上级得以喘息。
其实从这里我也突然悟出来了一个道理,握手是给了每级处理单元一个控制速度的权利。完美的流水线,应该来说是不需要通过握手来实现的(太理想了),因为还需要握手来控制数据的传输等等;
流水线中反压(拉低ready)
反压的目的都是为了屏蔽上级单元送数据来。但根据流水中的每级单元中是否有存储单元,可分为带存储器的反压和不带存储器的反压;在带存储器的反压根据对前级还是前前级的反压可分为:跨级反压、逐级反压;
不带存储器的反压
即流水线上的每一级都没有存储单元,后级与前级的耦合性高,当流水线中间某一级错误,导致整条流水线均停止工作;在上图中可以理解成,若C出于某种原因不能接收B_OUT,由于B中没有暂存空间,导致的结果就是B也不能接收A_OUT数据了。可以理解成工厂流水线里头,每一级都没有容器可以存放上一级的输出物。
特点:
1. 节省存储器资源,每一级都没有存储器;
2. 流水控制复杂,后级的流水停止,需对前面的每一级都有控制;(牵一发而动全身)
带存储器的逐级反压
如上图,和不带存储器的流水比起来,各级流水中都加入了一定的缓存容量。这样做的一个好处就是每一级与每一级之间的握手都变成了相对独立的握手模块。这里留个悬念,缓存的大小如何设定?
带存储器的跨级反压
如上图,C的反压直接跳过B,反压到A。目前我是没接触过这种设计,但是我认为这种设计也有一定的合理性以及局限性;这种结构需要求C可以无条件接收B_OUT数据,也就是单向握手,只要B给出B_OUT,C 100%可以接收;
握手与反压设计注意点
- sender发生数据的vld指示和receiver接收的ready指示应该为独立的逻辑产生,不可将二者扯上联系;
- 若存在流水,则是否为某一级流水添加存储单元、该存储单元多大都是需要考虑的点,出发点都是为了流水的效率;
- 流水除了考虑各级的存储深度外,不要忽略流水路上处理中的数据;
如有不当之处,欢迎交流讨论。
参考文章
数字芯片设计——握手与反压 - 知乎 (zhihu.com)
芯片设计-握手与反压(valid&ready) - 知乎 (zhihu.com)