在SpinalHDL里在顶层一键优化代码中Stream/Flow代码生成的payload,fragment。
难看的代码
来看一段代码:
import spinal.core._ import spinal.lib._ case class DataPort() extends Bundle{ val data0=UInt(8 bits) val data1=UInt(8 bits) } case class Demo() extends Component{ val io=new Bundle{ val sink=slave(Stream(Fragment(DataPort()))) val source=master(Stream(Fragment(DataPort()))) } noIoPrefix() io.source<
很简单的功能,一个Stream接口的Pipeline打拍。在生成RTL代码时会看到下面这种有点儿“不太舒服”的结构命名:
wire sink_s2mPipe_payload_last; wire [7:0] sink_s2mPipe_payload_fragment_data0; wire [7:0] sink_s2mPipe_payload_fragment_data1; reg sink_rValidN; reg sink_rData_last; reg [7:0] sink_rData_fragment_data0; reg [7:0] sink_rData_fragment_data1; wire sink_s2mPipe_m2sPipe_valid; wire sink_s2mPipe_m2sPipe_ready; wire sink_s2mPipe_m2sPipe_payload_last; wire [7:0] sink_s2mPipe_m2sPipe_payload_fragment_data0; wire [7:0] sink_s2mPipe_m2sPipe_payload_fragment_data1;
虽然说不怎么看生成的代码,但有时候别人看这里信号命名中间夹杂了一堆_payload_fragment_的信号还是略觉有点儿啰嗦。
尤其在用一些Axi/AxiLite总线时,当使用cloneOf时,会发现大量的信号名中间夹着一些paylaod字段,略觉不雅~
虽然这是Stream类的定义所导致,但如果去修改设计中的每一处总归还是比较麻烦的~
StreamRenameUtil
这里提供一个DIY的工具StreamRenameUtil,用于在设计的顶层一键让这种场景下的代码生成稍微优雅一些:
object StreamRenameUtil { def apply(topLevel:Component) = { Rename(topLevel,true) } def Rename(toplevel:Component,isCurrentComponentBoolean={ //current component process if(!isCurrentComponent){ toplevel.dslBody.foreachStatements{ case bt:BaseType if bt.parent.isInstanceOf[Stream[_]] => streamRename( bt.parent.asInstanceOf[Stream[_]]) case bt:BaseType if bt.parent.isInstanceOf[Flow[_]] => flowRename( bt.parent.asInstanceOf[Flow[_]]) case _ => } }else{ toplevel.dslBody.foreachStatements{ case bt:BaseType if bt.parent.isInstanceOf[Stream[_]] => toplevel.addPrePopTask(()=>{streamRename( bt.parent.asInstanceOf[Stream[_]])}) case bt:BaseType if bt.parent.isInstanceOf[Flow[_]] => toplevel.addPrePopTask(()=>{flowRename( bt.parent.asInstanceOf[Flow[_]])}) case _ => } } for(child<-toplevel.children){ Rename(child,false) } true } def streamRename(streamPort:Stream[_])={ streamPort.flatten.foreach((bt)=>{ val signalName=bt.getName() if(signalName.contains("fragment")){ bt.setName(signalName.replace("_payload_fragment_","_")) }else{ bt.setName(signalName.replace("_payload_","_")) } }) } def flowRename(flowPort:Flow[_])={ flowPort.flatten.foreach((bt)=>{ val signalName=bt.getName() if(signalName.contains("fragment")){ bt.setName(signalName.replace("_payload_fragment_","_")) }else{ bt.setName(signalName.replace("_payload_","_")) } }) } }
使用时仅需在顶层调用该方法,其会遍历设计中各模块的Stream、Flow类变量定义统一做修改:
case class Demo() extends Component{ val io=new Bundle{ val sink=slave(Stream(Fragment(DataPort()))) val source=master(Stream(Fragment(DataPort()))) } noIoPrefix() io.source<
最终代码生成会优雅一些:
wire sink_s2mPipe_valid; reg sink_s2mPipe_ready; wire sink_s2mPipe_last; wire [7:0] sink_s2mPipe_data0; wire [7:0] sink_s2mPipe_data1; reg sink_rValidN; reg sink_rData_last; reg [7:0] sink_rData_fragment_data0; reg [7:0] sink_rData_fragment_data1; wire sink_s2mPipe_m2sPipe_valid; wire sink_s2mPipe_m2sPipe_ready; wire sink_s2mPipe_m2sPipe_last; wire [7:0] sink_s2mPipe_m2sPipe_data0; wire [7:0] sink_s2mPipe_m2sPipe_data1; reg sink_s2mPipe_rValid; reg sink_s2mPipe_rData_last; reg [7:0] sink_s2mPipe_rData_fragment_data0; reg [7:0] sink_s2mPipe_rData_fragment_data1; wire when_Stream_l369;
这里的sink_s2mPipe_rData_fragment_data0、sink_s2mPipe_rData_fragment_data1为在打拍时生命的Fragment类型,非Stream类型,如果你实在看不惯也可以依样画葫芦添加一个对Fragment类型的Rename~
审核编辑:彭菁
全部0条评论
快来发表一下你的评论吧 !