在SpinalHDL里在顶层一键优化代码中Stream/Flow代码生成的payload,fragment。
难看的代码
来看一段代码:
importspinal.core._ importspinal.lib._ caseclassDataPort() extendsBundle{ val data0=UInt(8bits) val data1=UInt(8bits) } caseclassDemo() extendsComponent{ val io=newBundle{ val sink=slave(Stream(Fragment(DataPort()))) val source=master(Stream(Fragment(DataPort()))) } noIoPrefix() io.source<
很简单的功能,一个Stream接口的Pipeline打拍。在生成RTL代码时会看到下面这种有点儿“不太舒服”的结构命名:
wiresink_s2mPipe_payload_last; wire[7:0] sink_s2mPipe_payload_fragment_data0; wire[7:0] sink_s2mPipe_payload_fragment_data1; regsink_rValidN; regsink_rData_last; reg[7:0] sink_rData_fragment_data0; reg[7:0] sink_rData_fragment_data1; wiresink_s2mPipe_m2sPipe_valid; wiresink_s2mPipe_m2sPipe_ready; wiresink_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{ casebt:BaseType ifbt.parent.isInstanceOf[Stream[_]] => streamRename( bt.parent.asInstanceOf[Stream[_]]) casebt:BaseType ifbt.parent.isInstanceOf[Flow[_]] => flowRename( bt.parent.asInstanceOf[Flow[_]]) case_ => } }else{ toplevel.dslBody.foreachStatements{ casebt:BaseType ifbt.parent.isInstanceOf[Stream[_]] => toplevel.addPrePopTask(()=>{streamRename( bt.parent.asInstanceOf[Stream[_]])}) casebt:BaseType ifbt.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类变量定义统一做修改:
caseclassDemo() extendsComponent{ val io=newBundle{ val sink=slave(Stream(Fragment(DataPort()))) val source=master(Stream(Fragment(DataPort()))) } noIoPrefix() io.source<
最终代码生成会优雅一些:
wiresink_s2mPipe_valid; regsink_s2mPipe_ready; wiresink_s2mPipe_last; wire[7:0] sink_s2mPipe_data0; wire[7:0] sink_s2mPipe_data1; regsink_rValidN; regsink_rData_last; reg[7:0] sink_rData_fragment_data0; reg[7:0] sink_rData_fragment_data1; wiresink_s2mPipe_m2sPipe_valid; wiresink_s2mPipe_m2sPipe_ready; wiresink_s2mPipe_m2sPipe_last; wire[7:0] sink_s2mPipe_m2sPipe_data0; wire[7:0] sink_s2mPipe_m2sPipe_data1; regsink_s2mPipe_rValid; regsink_s2mPipe_rData_last; reg[7:0] sink_s2mPipe_rData_fragment_data0; reg[7:0] sink_s2mPipe_rData_fragment_data1; wirewhen_Stream_l369;
这里的sink_s2mPipe_rData_fragment_data0、sink_s2mPipe_rData_fragment_data1为在打拍时生命的Fragment类型,非Stream类型,如果你实在看不惯也可以依样画葫芦添加一个对Fragment类型的Rename~
审核编辑:彭菁
-
HDL
+关注
关注
8文章
327浏览量
47374 -
RTL
+关注
关注
1文章
385浏览量
59756 -
代码
+关注
关注
30文章
4779浏览量
68516 -
Stream
+关注
关注
0文章
20浏览量
7968
原文标题:逼死强迫症—优化Stream/Flow代码生成
文章出处:【微信号:Spinal FPGA,微信公众号:Spinal FPGA】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论