十二 · 2023年11月27日

pipeline高端玩法(十)—throwIt

✎ 编 者 按 

字如其名,来看下Pipeline中throwIt的用法,是怎么个丢弃方式

API

在Stage中,关于throwIt提供了下面的API:

image.png

函数中的动作出现了两个变量的使用:

  • internal.request.throws
  • internals.request.throwRoot

那么去到Pipeline里面看都哪里使用到了它。在看之前,先再来回顾下在SpinalHDL中pipeline的编程模型:

image.png

在Pipeline的模型里,Pipeline中的任何一级都是一个组合逻辑,如果它要驱动下一级Pipeline,那么其可以通过Connection来和下一级建立连接关系,最后一级则没有Connection。而在Connection中,则可以进行打拍。也即Stage中负责功能实现,Connection负责实现控制流水线级数,时序优化。

Connection中的作用

在Pipeline的build函数中,其定义了throwOne:

var throwOne = stage.internals.request.throws.nonEmpty generate orR(stage.internals.request.throws)

即如果internals.request.throws如果不为空,那么其中的所有条件取或后赋值给throwOne.

而后,在处理Stage间的连接关系时有:

image.png

这里对于驱动该级的Connection,首先将throwOne保留至clThrowOne(l)中,随后在if判断中,会为clThrowOneHit(l)声明为一个Bool()对象。在常用的Connection M2S、S2M中,alwasContainsSlaveToken均为true,故此时throwOne变量将会被赋值为null。

而对于:

if(throwOne != null) c.m.throwIt(throwOne, root = false)

由于此时throwOne重新被赋值为null,故并不会为驱动该Stage的Master调用throwIt,也即throw并不会向前级传输。

最终会调用下面的函数来进行Stage间的连接关系:

val area = l.on(m, s, clFlush(l), clFlushNext(l), clFlushNextHit(l), clThrowOne(l), clThrowOneHit(l))

clThrowOne(l)作为throwHead参数传入Connection的on函数。以M2S为例,我们来看下其在里面会有哪些动作:

m.ready match {  case null =>    s.valid := m.valid    (s.payload, m.payload).zipped.foreach(_ := _)  case r => {    if (flush != null && flushPreserveInput) s.valid clearWhen(flush)    if(throwHead != null) s.valid clearWhen(throwHead)    when(r) {      s.valid := m.valid    }    when(if (holdPayload) m.valid && r else r) {      (s.payload, m.payload).zipped.foreach(_ := _)    }  }}

可以看到,如果驱动Connection的Master没有ready信号,那么throwHead是没有任何作用的。

如果master具备ready信号,如果此时m.ready信号为低电平,那么作为Slave的Stage其input.valid将会在下一拍变为低电平。

Stage中的作用

在Stage中的作用比较简单,仅internals.request.throwRoot会起作用。在Pipeline中的build函数中:

if(s.request.throwsRoot.nonEmpty){  val doThrow = s.request.throwsRoot.orR  when(doThrow){    s.output.valid := False  }}

如果throwsRoot不为空,则其中任意一个条件满足是,Stage中的output.valid会立即清零。

结合Connection中throw的作用,throw会导致当前Stage的input.valid在下一拍清空(input.valid为寄存器),而默认情况下stage的output.valid(Wire)直接由input.valid驱动,故throwsRoot的作用就是让Stage的output.valid立即生效。比如说此时input.valid为高电平,ouput.ready也为高电平,throwsRoot将output.valid直接拉低避免当前拍的数据传输到下一级,从而实现立即丢掉。

Example

image.png

在这个例子中,如果cond为true,则stage2会立即丢掉当前传输至output端口的数据。

☆ END ☆

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

推荐阅读

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