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

spinal.lib.eda.xilinx.VivadoFlow.scala Maven / Gradle / Ivy

package spinal.lib.eda.xilinx

import java.io.File
import java.nio.file.Paths

import org.apache.commons.io.FileUtils
import spinal.core._
import spinal.lib.eda.bench.Report

import scala.sys.process._

object VivadoFlow {
  def doCmd(cmd : String): Unit ={
    println(cmd)
    if(isWindows)
      Process("cmd /C " + cmd) !
    else
      Process(cmd) !
  }
  def doCmd(cmd : String, path : String): Unit ={
    println(cmd)
    if(isWindows)
      Process("cmd /C " + cmd, new java.io.File(path)) !
    else
      Process(cmd, new java.io.File(path)) !

  }

  val isWindows = System.getProperty("os.name").toLowerCase().contains("win")

  def apply(vivadoPath : String,workspacePath : String,toplevelPath : String,family : String,device : String,frequencyTarget : HertzNumber = null,processorCount : Int = 1) : Report = {
    val projectName = toplevelPath.split("/").last.split("[.]").head
    val targetPeriod = (if(frequencyTarget != null) frequencyTarget else 400 MHz).toTime

    val workspacePathFile = new File(workspacePath)
    FileUtils.deleteDirectory(workspacePathFile)
    workspacePathFile.mkdir()
    FileUtils.copyFileToDirectory(new File(toplevelPath), workspacePathFile)


    val isVhdl = toplevelPath.endsWith(".vhd") || toplevelPath.endsWith(".vhdl")

    val tcl = new java.io.FileWriter(Paths.get(workspacePath,"doit.tcl").toFile)
    tcl.write(
s"""read_${if(isVhdl) "vhdl" else "verilog"} $toplevelPath
read_xdc doit.xdc

synth_design -part $device -top ${toplevelPath.split("\\.").head}
opt_design
place_design
route_design

report_utilization
report_timing"""
    )

    tcl.flush();
    tcl.close();


    val xdc = new java.io.FileWriter(Paths.get(workspacePath,"doit.xdc").toFile)
    xdc.write(s"""create_clock -period ${(targetPeriod*1e9) toBigDecimal} [get_ports clk]""")

    xdc.flush();
    xdc.close();

    doCmd(s"$vivadoPath/vivado -nojournal -log doit.log -mode batch -source doit.tcl", workspacePath)

    new Report{
      override def getFMax(): Double =  {
        import scala.io.Source
        val report = Source.fromFile(Paths.get(workspacePath,"doit.log").toFile).getLines.mkString
        val intFind = "-?(\\d+\\.?)+".r
        val slack = try {
          (family match {
            case "Artix 7" =>
              intFind.findFirstIn("-?(\\d+.?)+ns  \\(required time - arrival time\\)".r.findFirstIn(report).get).get
          }).toDouble
        }catch{
          case e : Exception => -1.0
        }
        return 1.0/(targetPeriod.toDouble-slack*1e-9)
      }
      override def getArea(): String =  {
        import scala.io.Source
        val report = Source.fromFile(Paths.get(workspacePath,"doit.log").toFile).getLines.mkString
        val intFind = "(\\d+,?)+".r
        val leArea = try {
          family match {
            case "Artix 7" =>
              intFind.findFirstIn("Slice LUTs[ ]*\\|[ ]*(\\d+,?)+".r.findFirstIn(report).get).get + " LUT " +
              intFind.findFirstIn("Slice Registers[ ]*\\|[ ]*(\\d+,?)+".r.findFirstIn(report).get).get + " FF "
          }
        }catch{
          case e : Exception => "???"
        }
        return leArea
      }
    }
  }

  def main(args: Array[String]) {
    val report = VivadoFlow(
      vivadoPath="/eda/Xilinx/Vivado/2017.2/bin",
      workspacePath="/home/spinalvm/tmp",
      toplevelPath="TopLevel.vhd",
      family="Artix 7",
      device="xc7k70t-fbg676-3",
      frequencyTarget = 1 MHz
    )
    println(report.getArea())
    println(report.getFMax())
  }
}


object QuartusTest {
  def main(args: Array[String]) {

    Paths.get("~")
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy