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

今天来看下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注册:
def overloaded(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) x   case none => stageabletodata(key)}  
    可以看出,这里的处理方式为,如果该变量在stageableoverloadedtodata中存在,那么会将stageableoverloadedtodata中的值赋值驱动stageableresultingtodata中对应的变量,否则将会从stageabletodata中寻找对应的变量进行驱动(上一步已经将对应的stageablekey注册进stageabletodata中)。
》show me the code
    分析完了源代码,上一个简单的example:
case class test3() extends component{  val io=new bundle{    val data_in=slave(flow(vec(uint(8 bits),4)))    val data_out=master(flow(uint(8 bits)))  }  noioprefix()  val a,b=stageable(uint(8 bits))  val pip=new pipeline{    val stage0=new stage{      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=new stage(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:
在这里,由于stage0中也包含a、b,故这里最终的驱动关系为:
再来看一个resulting和overlaoded共用的代码:
case class test4() extends component{  val io=new bundle{    val data_in=slave(flow(vec(uint(8 bits),4)))    val data_out=master(flow(uint(8 bits)))  }  noioprefix()  val a,b=stageable(uint(8 bits))  val pip=new pipeline{    val stage0=new stage{      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=new stage(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重载,结合上面的赋值顺序,最终的驱动关系为:
看到这里,可能会有一个疑问:为什么不能直接写成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内的电路对象驱动。


AR玩具的三大关键:技术、场景、内容
2011年展望:移动和无线正向企业IT走来
ZETA升降压DC-DC的工作路径和关键公式推导
硬件是使工业系统符合IEC 62443标准的关键
ADI研讨会:用于解决CDC和IDC难题的方法
怎样使用SpinalHDL Pipeline组件里的resulting及overloaded?
模组和PACK结构设计优化以及电池材料体系的优化升级
印制线路板几个常用标准
浅谈光纤特点
比特币还面临着哪些攻击威胁
自主移动机器人在动力电池领域大规模应用的契机已经到来
怎么连接PLC和变频器
三星Galaxy A11框架曝光,将配备后置四摄像头
如何监控电路板切割尺寸的解决方案
国产MCU有多卷——合宙Air001开发板新品上市,羊毛芯片只要0.01元?!
5G业务简化是真是假
人工智能技术正在彻底改变临床研究
VR业务正在逐渐成为HTC的核心业务
华为Mate 20红色真机曝光,后置三摄像头搭配麒麟980
记忆黑板与存储空间:探讨其限制与可能性