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
|
Artix 7 -> 346 Mhz 481 LUT 539 FF
|
||||||
Cyclone V -> 201 Mhz 347 ALMs
|
Cyclone V -> 201 Mhz 347 ALMs
|
||||||
Cyclone IV -> 190 Mhz 673 LUT 529 FF
|
Cyclone IV -> 190 Mhz 673 LUT 529 FF
|
||||||
|
iCE40 -> 81 Mhz 1130 LC
|
||||||
|
|
||||||
VexRiscv smallest (RV32I, 0.52 DMIPS/Mhz, no datapath bypass) ->
|
VexRiscv smallest (RV32I, 0.52 DMIPS/Mhz, no datapath bypass) ->
|
||||||
Artix 7 -> 340 Mhz 562 LUT 589 FF
|
Artix 7 -> 340 Mhz 562 LUT 589 FF
|
||||||
Cyclone V -> 202 Mhz 387 ALMs
|
Cyclone V -> 202 Mhz 387 ALMs
|
||||||
Cyclone IV -> 180 Mhz 780 LUT 579 FF
|
Cyclone IV -> 180 Mhz 780 LUT 579 FF
|
||||||
|
iCE40 -> 71 Mhz 1278 LC
|
||||||
|
|
||||||
VexRiscv small and productive (RV32I, 0.82 DMIPS/Mhz) ->
|
VexRiscv small and productive (RV32I, 0.82 DMIPS/Mhz) ->
|
||||||
Artix 7 -> 327 Mhz 698 LUT 558 FF
|
Artix 7 -> 327 Mhz 698 LUT 558 FF
|
||||||
Cyclone V -> 158 Mhz 524 ALMs
|
Cyclone V -> 158 Mhz 524 ALMs
|
||||||
Cyclone IV -> 146 Mhz 1,061 LUT 552 FF
|
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$) ->
|
VexRiscv small and productive with I$ (RV32I, 0.72 DMIPS/Mhz, 4KB-I$) ->
|
||||||
Artix 7 -> 331 Mhz 727 LUT 600 FF
|
Artix 7 -> 331 Mhz 727 LUT 600 FF
|
||||||
Cyclone V -> 152 Mhz 536 ALMs
|
Cyclone V -> 152 Mhz 536 ALMs
|
||||||
Cyclone IV -> 156 Mhz 1,075 LUT 565 FF
|
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) ->
|
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
|
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.core._
|
||||||
import spinal.lib.eda.bench._
|
import spinal.lib.eda.bench._
|
||||||
|
import spinal.lib.eda.icestorm.IcestormStdTargets
|
||||||
import vexriscv.VexRiscv
|
import vexriscv.VexRiscv
|
||||||
import vexriscv.plugin.DecoderSimplePlugin
|
import vexriscv.plugin.{DecoderSimplePlugin, KeepAttribute}
|
||||||
|
|
||||||
import scala.collection.mutable.ArrayBuffer
|
import scala.collection.mutable.ArrayBuffer
|
||||||
|
|
||||||
|
@ -14,6 +15,11 @@ object VexRiscvSynthesisBench {
|
||||||
def main(args: Array[String]) {
|
def main(args: Array[String]) {
|
||||||
|
|
||||||
def wrap(that : => Component) : Component = that
|
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
|
// Wrap with input/output registers
|
||||||
// def wrap(that : => Component) : Component = {
|
// def wrap(that : => Component) : Component = {
|
||||||
// //new WrapWithReg.Wrapper(that)
|
// //new WrapWithReg.Wrapper(that)
|
||||||
|
@ -105,8 +111,9 @@ object VexRiscvSynthesisBench {
|
||||||
) ++ AlteraStdTargets(
|
) ++ AlteraStdTargets(
|
||||||
quartusCycloneIVPath = "/eda/intelFPGA_lite/17.0/quartus/bin",
|
quartusCycloneIVPath = "/eda/intelFPGA_lite/17.0/quartus/bin",
|
||||||
quartusCycloneVPath = "/eda/intelFPGA_lite/17.0/quartus/bin"
|
quartusCycloneVPath = "/eda/intelFPGA_lite/17.0/quartus/bin"
|
||||||
)
|
) ++ IcestormStdTargets()
|
||||||
|
|
||||||
|
// val targets = IcestormStdTargets()
|
||||||
Bench(rtls, targets, "/eda/tmp/")
|
Bench(rtls, targets, "/eda/tmp/")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue