在SpinalHDL里在顶层一键优化Stream/Flow代码生成

描述

    在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~

        审核编辑:彭菁

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分