All Downloads are FREE. Search and download functionalities are using the official Maven repository.

spinal.lib.bus.regif.Doc.DocSVHeader.scala Maven / Gradle / Ivy

The newest version!
package spinal.lib.bus.regif

import spinal.lib._
import spinal.lib.bus.regif.AccessType._

import scala.math

final case class DocSVHeader(name : String,
                             override val prefix: String = "",
                             withshiftmask: Boolean = true) extends BusIfDoc {
  override val suffix: String = "svh"

  def guardName : String = s"${name}_REGIF_H"

  def body(): String = {
    val maxnamelen = bi.slices.map(_.getName().size).max + prefix.length
    val maxshiftlen = bi.slices.map(t => t.getName().size + t.fdNameLens).max + prefix.length
    val normalRegSlices = bi.regSlicesNotReuse
    val reuseGroupsById = bi.reuseGroupsById
    s"""|/*
        | * ${header}
        | * Reg Interface SV-Header [AUTOGENERATE by SpinalHDL]
        | */
        |
        |`ifndef ${guardName}
        |`define ${guardName}
        |
        |${normalRegSlices.map(_.define(maxnamelen, maxshiftlen)).mkString("\n")}
        |
        |${reuseDeclare(reuseGroupsById)}
        |
        |`endif /* ${guardName} */
        |""".stripMargin
  }

  def reuseDeclare(lst: Map[String, Map[Int, List[RegSlice]]]) = {

    def base(name: String, t: RegSlice, max: Int) = {
      val alignName = s"%-${max}s".format(t.reuseTag.instName)
      val defineName = s"${name}_base_${alignName}".toUpperCase()
      s"`define ${defineName}  0x${t.reuseTag.baseAddr.hexString()}"
    }

    lst.map{ t =>
      val partName = t._1
      val decPart: List[RegSlice]  = t._2.head._2
      val heads : List[RegSlice] = t._2.map(_._2.head).toList.sortBy(_.reuseTag.id)

      val instNameMaxLens = heads.map(_.reuseTag.instName.size).max
      val maxnamelen = decPart.map(_.getName().size).max + prefix.length
      val maxshiftlen = decPart.map(t => t.getName().size + t.fdNameLens).max + prefix.length

      s"""
        |/* part '${partName}' declare --> */
        |${heads.map(t => base(partName, t, instNameMaxLens)).mkString("\n")}
        |/* part '${partName}' defines */
        |${decPart.map(_.baseDefine(maxnamelen, maxshiftlen)).mkString("\n")}
        |/* <--- part '${partName}' declare */
        |""".stripMargin
    }.mkString("")
  }

  def nameDedupliaction(repeat: String, word: String) = word.toUpperCase().replaceAll(repeat.toUpperCase() + "_", "")

  implicit class RegSliceCheadExtend(reg: RegSlice) {
    val deDupRegName = nameDedupliaction(prefix, reg.getName())
    val preFixRegName = (if(prefix.isEmpty) deDupRegName else s"${prefix}_${deDupRegName}").toUpperCase()

    def define(maxreglen: Int, maxshiftlen: Int): String = {
      val _tab = " " * (maxreglen - deDupRegName.size)
      s"""`define ${preFixRegName} ${_tab}0x${reg.getAddr().hexString(16)}${fddefine(maxshiftlen)}""".stripMargin
    }

    def baseDefine(maxreglen: Int, maxshiftlen: Int) = {
      val _tab = " " * (maxreglen - deDupRegName.size)
      s"""`define ${preFixRegName}(base)  ${_tab}base + 0x${(reg.getAddr() - reg.reuseTag.baseAddr).hexString(8)}${fddefine(maxshiftlen)}""".stripMargin
    }

    def fdNameLens = math.max("reserved_0".size, reg.getFields().map(_.getName.size).max)

    def fddefine(maxlen: Int): String = {
      val nmaxlen = maxlen - preFixRegName.size
      if (withshiftmask) {
        val t = reg.getFields().map(t => t.define(preFixRegName, nmaxlen, prefix)).filterNot(_.isEmpty).mkString("\n")
        if (t.isEmpty) "" else "\n" + t
      } else ""
    }
  }

  implicit class FieldCHeadExtend(fd: Field) {
    def define(pre: String, tabn: Int = 0, duplicate: String = ""): String = {
      //add Define  XXX_SHIFT   XXX_MASK  for SW bit operation
      def lsb: Int = fd.getSection().min

      def msb: Int = fd.getSection().max

      def mask = BigInt((1 << fd.getSection().size) - 1) << lsb

      val newfdname = nameDedupliaction(duplicate, fd.getName())
      val _tab = " " * (tabn - newfdname.size)
      fd.getAccessType() match {
        case `NA` => ""
        case `W1S` | `W1C` | `W1T` | `W1P` | `W1CRS` | `W1SRC` | `W1SHS` | `W1CHS` => s"""`define ${pre}_${newfdname}_SHIFT ${_tab}${lsb} /*${fd.getName()} 1bit*/""".stripMargin
        case `W0S` | `W0C` | `W0T` | `W0P` | `W0CRS` | `W0SRC` => s"""`define ${pre}_${newfdname}_SHIFT ${_tab}${lsb} /*${fd.getName()} 1bit*/""".stripMargin
        case _ => {
          if (fd.getSection().size == bi.busDataWidth) "" else if (fd.getName() == "_bm_") "" else
            s"""`define ${pre}_${newfdname}_SHIFT ${_tab}${lsb}
               |`define ${pre}_${newfdname}_MASK  ${_tab}0x${mask.hexString(32)} /* ${fd.getName()}, ${fd.getAccessType()}, ${fd.getWidth()} bit */""".stripMargin
        }
      }
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy