在前面的系列文章中,已基本阐述了Pipeline中的用法,本篇做个总结,重点针各方法的优先级
》last Win
无论是SystemVerilog还是SpinalHDL,都有Last valid assignment wins的语法特征。如在SpinalHDL-Doc中所描述:
// Every clock cycle evaluation starts here val paramIsFalse = false val x, y = Bool() // Define two combinational signals val result = UInt(8 bits) // Define a combinational signal result := 1 when(x) { result := 2 when(y) { result := 3 } } if(paramIsFalse) { // This assignment should win as it is last, but it was never elaborated result := 4 // into hardware due to the use of if() and it evaluating to false at the time }
对应的真值表是:
那么在使用pipeline中,你可能会这么来写:
when(cond1){ haltIt() } when(cond2){ spawnIt() }
参照上面所述的Last valid assignment wins的语法特征,你可能认为spawnIt的优先级是高于haltIt的~
然而,并非如此。
Pipeline的构建并不是我们在直接构建,而是我们描述了流水线的规则之后交由Pipeline的build函数来搭建起整个的流水线结构。既然不是我们直接搭建电路,那么就要注意下在流水线构建过程中这些方法的优先级了。
回到Pipeline的组成结构:
Pipeline包含Stage和Connection两大主体。在Pipeline的build构建中,分别对应了Internal Connection及InInterconnect Connection两部分。
》Internal Connection中的优先级
来看下在Pipeline中关于Internal Connection的处理:
在之前的文章系列中已基本分析了每个小单元的用法(forks暂时不考虑)。对于每一级Stage,默认情况下Stage的output端口和input端口是直连的。而后自上到下对应的API处理分别是:
spawnIt
flushIt(root为true)
throwIt(root为true)
haltIt
按照Last valid assignment wins的原则,那么上面对应的API则是优先级从高到低的。
》Interconnect Connection中的优先级
这里还是以Pipeline中常用的M2S为例来看待Interconnect Connection中的处理方式:
这里我们要区分来看:
m.ready存在(对应前一级Stage的output.ready)
m.ready不存在
先来看m.ready不存在的场景。当m.ready不存在时,上面的处理流程牵涉到的API有:
flushIt(line30)
flushNext(line31)
按照Last valid assignment wins的原则,那么上面对应的API则是优先级从高到低的。
而当m.ready存在时,则牵涉到的API有:
throwIt(line19)
flushIt(line 30)
flushNext(line 31)
按照Last valid assignment wins的原则,那么上面对应的API则是优先级从高到低的。
》写在最后
对于SpinalHDL Pipeline这个“勇者的游戏”系列,至此基本总结的差不多了。写文章相比于看代码还是要费事一些。对于Pipeline这个系列,最开始驱使我去研究来源于想对Cache的了解,看着dolu的代码如看天书。不得不说Pipeline的这个设计简直“惊为天人”!对于逻辑设计来讲无非两大核心:状态机,流水线。在看Pipeline之前觉得这个Lib真抽象,真正看完分析后觉得真香,之前自己的设计简直太Low了,这里简直把高效描述电路发挥到了极致~
审核编辑:刘清
全部0条评论
快来发表一下你的评论吧 !