Add ice40 synthesis results
This commit is contained in:
parent
bdcf3f6234
commit
558af595a1
|
@ -67,21 +67,25 @@ VexRiscv smallest (RV32I, 0.52 DMIPS/Mhz, no datapath bypass, no interrupt) ->
|
|||
Artix 7 -> 346 Mhz 481 LUT 539 FF
|
||||
Cyclone V -> 201 Mhz 347 ALMs
|
||||
Cyclone IV -> 190 Mhz 673 LUT 529 FF
|
||||
iCE40 -> 81 Mhz 1130 LC
|
||||
|
||||
VexRiscv smallest (RV32I, 0.52 DMIPS/Mhz, no datapath bypass) ->
|
||||
Artix 7 -> 340 Mhz 562 LUT 589 FF
|
||||
Cyclone V -> 202 Mhz 387 ALMs
|
||||
Cyclone IV -> 180 Mhz 780 LUT 579 FF
|
||||
iCE40 -> 71 Mhz 1278 LC
|
||||
|
||||
VexRiscv small and productive (RV32I, 0.82 DMIPS/Mhz) ->
|
||||
Artix 7 -> 327 Mhz 698 LUT 558 FF
|
||||
Cyclone V -> 158 Mhz 524 ALMs
|
||||
Cyclone IV -> 146 Mhz 1,061 LUT 552 FF
|
||||
|
||||
iCE40 -> 55 Mhz 1541 LC
|
||||
|
||||
VexRiscv small and productive with I$ (RV32I, 0.72 DMIPS/Mhz, 4KB-I$) ->
|
||||
Artix 7 -> 331 Mhz 727 LUT 600 FF
|
||||
Cyclone V -> 152 Mhz 536 ALMs
|
||||
Cyclone IV -> 156 Mhz 1,075 LUT 565 FF
|
||||
iCE40 -> 54 Mhz 1686 LC
|
||||
|
||||
VexRiscv full no cache (RV32IM, 1.22 DMIPS/Mhz, single cycle barrel shifter, debug module, catch exceptions, static branch) ->
|
||||
Artix 7 -> 295 Mhz 1399 LUT 971 FF
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
package spinal.lib.eda.icestorm
|
||||
import spinal.lib.eda._
|
||||
import spinal.lib.eda.bench.{Report, Rtl, Target}
|
||||
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
import java.io.File
|
||||
import java.nio.file.Paths
|
||||
|
||||
import org.apache.commons.io.FileUtils
|
||||
import spinal.core._
|
||||
import spinal.lib.StreamFifo
|
||||
import spinal.lib.eda.bench.Report
|
||||
|
||||
import scala.sys.process._
|
||||
|
||||
object IcestormFlow {
|
||||
def doCmd(cmd : Seq[String], path : String): String ={
|
||||
println(cmd)
|
||||
val str = new StringBuilder()
|
||||
val log = new ProcessLogger {
|
||||
override def err(s: => String): Unit = {
|
||||
str ++= s
|
||||
stderr.println(s)
|
||||
}
|
||||
|
||||
override def out(s: => String): Unit = {
|
||||
str ++= s
|
||||
stdout.println(s)
|
||||
}
|
||||
|
||||
override def buffer[T](f: => T) = f
|
||||
}
|
||||
if(isWindows)
|
||||
Process("cmd /C " + cmd, new java.io.File(path)) !(log)
|
||||
else
|
||||
Process.apply(cmd, new java.io.File(path)) !(log)
|
||||
|
||||
return str.toString()
|
||||
}
|
||||
|
||||
val isWindows = System.getProperty("os.name").toLowerCase().contains("win")
|
||||
|
||||
def apply(workspacePath : String,toplevelPath : String,family : String,device : String, pack : String) : Report = {
|
||||
val projectName = toplevelPath.split("/").last.split("[.]").head
|
||||
|
||||
|
||||
|
||||
val workspacePathFile = new File(workspacePath)
|
||||
FileUtils.deleteDirectory(workspacePathFile)
|
||||
workspacePathFile.mkdir()
|
||||
FileUtils.copyFileToDirectory(new File(toplevelPath), workspacePathFile)
|
||||
doCmd(List("yosys", "-v3", "-p", s"synth_ice40 -top $projectName -blif ${projectName}.blif", s"$projectName.v" ), workspacePath)
|
||||
val arachne = doCmd(List("arachne-pnr", "-d", device.replace("hx",""), "--max-passes", "600", "-P", pack, s"$projectName.blif" ,"-o", s"$projectName.asc"), workspacePath)
|
||||
doCmd(List("icepack", s"$projectName.asc", s"$projectName.bin"), workspacePath)
|
||||
val icetime = doCmd(List("icetime", "-tmd", device, s"${projectName}.asc"), workspacePath)
|
||||
new Report{
|
||||
val intFind = "(\\d+,?)+".r
|
||||
val fMaxReg = """[-+]?(\d*[.])?\d+""".r
|
||||
override def getFMax() = {
|
||||
try {
|
||||
fMaxReg.findAllMatchIn("Total path delay: [^\\n]* MHz".r.findFirstIn(icetime).get).drop(1).next.toString().toDouble * 1e6
|
||||
} catch {
|
||||
case e : Throwable => -1
|
||||
}
|
||||
}
|
||||
override def getArea() = {
|
||||
try {
|
||||
intFind.findFirstIn("LCs[^\\n]*\\/".r.findFirstIn(arachne).get).get.toString() + " LC"
|
||||
} catch {
|
||||
case e : Throwable => "error"
|
||||
}
|
||||
}
|
||||
}
|
||||
// mkdir -p bin
|
||||
// rm -f Murax.v*.bin
|
||||
// cp ../../../Murax.v*.bin . | true
|
||||
// yosys -v3 -p "synth_ice40 -top toplevel -blif bin/toplevel.blif" ${VERILOG}
|
||||
//
|
||||
// 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]) {
|
||||
SpinalVerilog(StreamFifo(Bits(8 bits), 64))
|
||||
val report = IcestormFlow(
|
||||
workspacePath="/home/spinalvm/tmp",
|
||||
toplevelPath="VexRiscv.v",
|
||||
family="iCE40",
|
||||
device="hx8k",
|
||||
pack = "ct256"
|
||||
)
|
||||
println(report.getArea())
|
||||
println(report.getFMax())
|
||||
}
|
||||
}
|
||||
|
||||
object IcestormStdTargets {
|
||||
def apply(): Seq[Target] = {
|
||||
val targets = ArrayBuffer[Target]()
|
||||
targets += new Target {
|
||||
override def getFamilyName(): String = "iCE40"
|
||||
override def synthesise(rtl: Rtl, workspace: String): Report = {
|
||||
IcestormFlow(
|
||||
workspacePath=workspace,
|
||||
toplevelPath=rtl.getRtlPath(),
|
||||
family=getFamilyName(),
|
||||
device="hx8k",
|
||||
pack = "ct256"
|
||||
)
|
||||
}
|
||||
}
|
||||
targets
|
||||
}
|
||||
}
|
|
@ -2,8 +2,9 @@ package vexriscv.demo
|
|||
|
||||
import spinal.core._
|
||||
import spinal.lib.eda.bench._
|
||||
import spinal.lib.eda.icestorm.IcestormStdTargets
|
||||
import vexriscv.VexRiscv
|
||||
import vexriscv.plugin.DecoderSimplePlugin
|
||||
import vexriscv.plugin.{DecoderSimplePlugin, KeepAttribute}
|
||||
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
|
||||
|
@ -14,6 +15,11 @@ object VexRiscvSynthesisBench {
|
|||
def main(args: Array[String]) {
|
||||
|
||||
def wrap(that : => Component) : Component = that
|
||||
// def wrap(that : => Component) : Component = {
|
||||
// val c = that
|
||||
// c.getAllIo.foreach(io => KeepAttribute(io.asDirectionLess()))
|
||||
// c
|
||||
// }
|
||||
// Wrap with input/output registers
|
||||
// def wrap(that : => Component) : Component = {
|
||||
// //new WrapWithReg.Wrapper(that)
|
||||
|
@ -105,8 +111,9 @@ object VexRiscvSynthesisBench {
|
|||
) ++ AlteraStdTargets(
|
||||
quartusCycloneIVPath = "/eda/intelFPGA_lite/17.0/quartus/bin",
|
||||
quartusCycloneVPath = "/eda/intelFPGA_lite/17.0/quartus/bin"
|
||||
)
|
||||
) ++ IcestormStdTargets()
|
||||
|
||||
// val targets = IcestormStdTargets()
|
||||
Bench(rtls, targets, "/eda/tmp/")
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue