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

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

3天内不再提示

怎样使用SpinalHDL Pipeline组件里的resulting及overloaded?

Spinal FPGA 来源:Spinal FPGA 2023-09-11 09:47 次阅读

今天来看下SpinalHDL Pipeline组件里的resulting及overloaded的使用

》resulting

在Stage中的数据结构中,有四种类型:

val stageableToData = mutable.LinkedHashMap[StageableKey, Data]()
val stageableOverloadedToData = mutable.LinkedHashMap[StageableKey, Data]()
val stageableResultingToData = mutable.LinkedHashMap[StageableKey, Data]()
val stageableTerminal = mutable.LinkedHashSet[StageableKey]()

关于stageableToData,在之前的文章中已有介绍,今天来看下stageableOverloadedToData以及stageableResultingToData的作用。在提供的API中,相关的注册函数有:

stageableOverloadedToData注册:

defoverloaded(key : StageableKey):Data = {
internals.stageableOverloadedToData.getOrElseUpdate(key, ContextSwapper.outsideCondScope{
key.stageable()//.setCompositeName(this, s"${key}_overloaded")
})
}

stageableResultingToData注册:

def resulting(key : StageableKey) : Data = {
internals.stageableResultingToData.getOrElseUpdate(key, ContextSwapper.outsideCondScope{
key.stageable()//.setCompositeName(this, s"${key}_overloaded")
})
}
def resulting[T <: Data](key : Stageable[T]) : T = {
    resulting(StageableKey(key.asInstanceOf[Stageable[Data]], null)).asInstanceOf[T]
  }
def resulting[T <: Data](key : Stageable[T], key2 : Any) : T = {
    resulting(StageableKey(key.asInstanceOf[Stageable[Data]], key2)).asInstanceOf[T]
}

字如其名,resulting可以理解为获取Stageable的最终结果,而overload则是对数据的重载。不妨先来看看在pipeline中这两种类型所起的作用:

在pipeline的build函数里,对于stageableResultingToData,其首先的处理方式代码如下:

for(s <- stagesSet){
   for(key <- s.internals.stageableResultingToData.keys){
     s.apply(key)
   }
}

这里对于每个stage中stageableResultingToData里所注册的每种类型StageableKey,其都会调用Stage的apply函数将其注册到StageableToData中,也就意味着如果前级也有该对应的StageableKey,那么在连接阶段两者是可以建立连接关系的。

随后,在internal conntection阶段,对于stageableResultingToData中的变量,采用的赋值逻辑为:

for((key, value) <- s.internals.stageableResultingToData){
   value := s.internals.outputOf(key)
}

而outputOf的赋值逻辑为:

def outputOf(key : StageableKey) = stageableOverloadedToData.get(key) match {
caseSome(x) => x
caseNone => stageableToData(key)
}

可以看出,这里的处理方式为,如果该变量在stageableOverloadedToData中存在,那么会将stageableOverloadedToData中的值赋值驱动stageableResultingToData中对应的变量,否则将会从stageableToData中寻找对应的变量进行驱动(上一步已经将对应的StageableKey注册进stageableToData中)。

》Show Me The Code

分析完了源代码,上一个简单的example:

caseclassTest3() extendsComponent{
val io=newBundle{
val data_in=slave(Flow(Vec(UInt(8bits),4)))
val data_out=master(Flow(UInt(8bits)))
}
noIoPrefix()
val A,B=Stageable(UInt(8bits))
val pip=newPipeline{
val stage0=newStage{
this.internals.input.valid:=io.data_in.valid
A:=io.data_in.payload(0)+io.data_in.payload(1)
B:=io.data_in.payload(2)+io.data_in.payload(3)
}
val stage1=newStage(Connection.M2S()){
io.data_out.payload:=resulting(A)+resulting(B)
io.data_out.valid:=this.internals.output.valid
}
}
pip.build()
}

在这个例子里,在stage1中仅用到了resulting语句。按前面所述,stage1中最终stageableResultingToData中会包含两个变量,build阶段也会向其stageableToData阶段注册两个变量A、B:

6f1ef2ca-4fc0-11ee-a25d-92fbcf53809c.jpg

在这里,由于stage0中也包含A、B,故这里最终的驱动关系为:

6f38a990-4fc0-11ee-a25d-92fbcf53809c.jpg

再来看一个resulting和overlaoded共用的代码:

caseclass Test4() extends Component{
val io=newBundle{
val data_in=slave(Flow(Vec(UInt(8bits),4)))
val data_out=master(Flow(UInt(8bits)))
}
noIoPrefix()
val A,B=Stageable(UInt(8bits))
val pip=newPipeline{
val stage0=newStage{
this.internals.input.valid:=io.data_in.valid
A:=io.data_in.payload(0)+io.data_in.payload(1)
B:=io.data_in.payload(2)+io.data_in.payload(3)
}
val stage1=newStage(Connection.M2S()){
io.data_out.payload:=resulting(A)+B
io.data_out.valid:=this.internals.output.valid
overloaded(A):=A+1
}
}
pip.build()
}

这里在stage1中对A调用了overloaded重载,结合上面的赋值顺序,最终的驱动关系为:

6f4e3800-4fc0-11ee-a25d-92fbcf53809c.jpg

看到这里,可能会有一个疑问:为什么不能直接写成A:=A+1的形式呢?主要在于A本身处于StageableToData,在进行Stage之间的连接时已经对齐进行赋值驱动,这里如果直接写成A:=A+1相当于对电路进行重复驱动,从而导致报错。

》总结

resulting&overloaded主要用于在某个Stage阶段对电路在结合上一Stage基础上需做一些额外判断对该阶段的相应电路做新的赋值驱动时进行处理。如在NaxRsicV中Cache里的一些电路处理:

overloaded(BANK_BUSY)(bankId) := BANK_BUSY(bankId) || bank.write.valid && REDO_ON_DATA_HAZARD

在流水线的某一阶段在保持Stageable语义而不必新增Stageable情况下通过overlaoded、resulting来进行Stage内的电路对象驱动。






审核编辑:刘清

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

    关注

    68

    文章

    19083

    浏览量

    228739
  • 驱动器
    +关注

    关注

    52

    文章

    8081

    浏览量

    145756
  • Pipeline
    +关注

    关注

    0

    文章

    28

    浏览量

    9332
  • HDL语言
    +关注

    关注

    0

    文章

    46

    浏览量

    8905
  • cache技术
    +关注

    关注

    0

    文章

    41

    浏览量

    1043

原文标题:pipeline高端玩法(六)—resulting&overloaded

文章出处:【微信号:Spinal FPGA,微信公众号:Spinal FPGA】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    SpinalHDLpipeline的设计思路

    如果你曾看过VexRSICV的设计,对于从事逻辑设计的你会惊讶从未想过逻辑设计还能这么来做。
    的头像 发表于 08-12 11:22 1195次阅读

    SpinalHDLswitch方法有何用处呢

    ,当我们需要根据tkeep信号来计算这一拍有多少有效数据时这里的代码会是什么样子……这种代码写的手有点儿累(又没啥技术含量)……在SpinalHDL该如何做呢?switchSpinalHDL提供了
    发表于 06-22 14:25

    SpinalHDL实现优雅的添加待跟踪波形信号

    在FPGA的开发过程中,在线抓取波形往往是终极调试大法。而如何抓取信号,相信做逻辑开发的小伙伴都是轻车熟路,张口就来,无非两种方式嘛:待跟踪信号添加原语或者手动例化Ila。而在SpinalHDL
    发表于 06-22 14:37

    谈谈SpinalHDL中StreamCCByToggle组件设计不足的地方

    StreamCCByToggle的原理,可参照前文所提到的文章,这里不再做过多赘述,小伙伴们也可以自行去阅读SpinalHDL的源代码。我们看下面的波形:    在刚开始dataIn发送了一个任务,导致
    发表于 06-30 15:11

    SpinalHDL中关于casez的使用

    Verilog代码时还是很少会直接这么来写的,往往通常采用casez来进行描述:那么在SpinalHDL中,我们是否也可以这么描述呢?SpinalHDL中的don't care像Verilog代码中,casez
    发表于 07-06 10:59

    分享一个在SpinalHDLapply的有趣用法

    SpinalHDL和Chisel都是基于scala来实现的,而在SpinalHDL的example,偶然看到一个apply的有趣用法。“神奇”的逻辑,"奇葩"的写法偶然看到一
    发表于 07-19 15:08

    SpinalHDL是如何让仿真跑起来的

    SpinalHDL,当我们的设计完成后如果说把生成的Verilog/SystemVerilog代码用SystemVerilog来进行仿真验证那真是一件痛苦的事情,而且对于SystemVerilog本身来讲,在
    发表于 07-25 15:09

    如何在SpinalHDL启动一个仿真

    前言在安装完成Verilator、GtkWave后,我们即可在IDEA通过SpinalHDL提供的仿真接口来对我们的设计进行仿真。在《SpinalHDL—仿真环境》一文中已提到SpinalH
    发表于 07-26 16:59

    SpinalHDL时钟域中的定制与命名

    聊一聊在SpinalHDL时钟域中时钟的定制与命名。 相较于Verilog,在SpinalHDL,其对时钟域有着更细致的描述,从而也能够更精细的控制和描述。而对于时钟域,我们往往关
    的头像 发表于 03-22 10:14 2094次阅读

    SpinalHDL用于跨时钟域处理的一些手段方法

    每一个做数字逻辑的都绕不开跨时钟域处理,谈一谈SpinalHDL用于跨时钟域处理的一些手段方法。
    的头像 发表于 07-11 10:51 1763次阅读

    SpinalHDL运行VCS+Vivado相关仿真

    本篇文章来源于微信群中的网友,分享下在SpinalHDL如何丝滑的运行VCS跑Vivado相关仿真。自此仿真设计一体化不是问题。
    的头像 发表于 08-10 09:15 2406次阅读

    SpinalHDL如何实现Sobel边缘检测

    书接上文,趁着今天休假,采用SpinalHDL做一个小的demo,看看在SpinalHDL如何优雅的实现Sobel边缘检测。
    的头像 发表于 08-26 08:59 1241次阅读

    SpinalHDLpipeline的设计思路

    如果你曾看过VexRSICV的设计,对于从事逻辑设计的你会惊讶从未想过逻辑设计还能这么来做。针对VexRSICV所衍生出的pipeline Lib,该系列会对pipeline进行一次梳理。诚如之前一篇博客曾讲,这是“勇者的游戏”。
    的头像 发表于 08-16 15:11 900次阅读
    <b class='flag-5'>SpinalHDL</b><b class='flag-5'>里</b><b class='flag-5'>pipeline</b>的设计思路

    SpinalHDL在顶层一键优化Stream/Flow代码生成

        在SpinalHDL在顶层一键优化代码中Stream/Flow代码生成的payload,fragment。 难看的代码       来看一段代码:   import
    的头像 发表于 12-14 09:05 617次阅读

    浅析SpinalHDLPipeline中的复位定制

    之前有系列文章介绍了SpinalHDLPipeline的使用,最近在一个功能模块中真实的使用了这个lib。
    的头像 发表于 03-17 17:31 962次阅读
    浅析<b class='flag-5'>SpinalHDL</b>中<b class='flag-5'>Pipeline</b>中的复位定制