在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文章
328瀏覽量
47468 -
RTL
+關注
關注
1文章
385瀏覽量
59951 -
代碼
+關注
關注
30文章
4827瀏覽量
69055 -
Stream
+關注
關注
0文章
20瀏覽量
8006
原文標題:逼死強迫癥—優化Stream/Flow代碼生成
文章出處:【微信號:Spinal FPGA,微信公眾號:Spinal FPGA】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論