
spinal.lib.eda.bench.Bench.scala Maven / Gradle / Ivy
package spinal.lib.eda.bench
import spinal.core._
import spinal.lib.{KeepAttribute, StreamFifo}
import spinal.sim.SimManager
import java.util.concurrent.ForkJoinPool
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, Future}
import scala.collection.Seq
import scala.util.Random
/**
* Created by PIC32F_USER on 16/07/2017.
*/
trait Rtl {
/** Name */
def getName(): String
/** Path of top module RTL */
def getRtlPath() : String = getRtlPaths().head
/** A List of RTL paths */
def getRtlPaths() : Seq[String] = Seq(getRtlPath())
/** The top module name, defaulting to the file name of top module RTL */
def getTopModuleName() : String = getRtlPath().split("\\.").head
}
object Rtl {
/** Create Rtl from SpinalReport */
def apply[T <: Component](rtl: SpinalReport[T]): Rtl = {
new Rtl {
override def getName(): String = rtl.toplevelName
override def getRtlPaths(): Seq[String] = rtl.rtlSourcesPaths.toSeq
override def getTopModuleName(): String = rtl.toplevelName
}
}
def ffIo[T <: Component](c : T): T ={
def buf1[T <: Data](that : T) = KeepAttribute(RegNext(that)).addAttribute("DONT_TOUCH")
def buf[T <: Data](that : T) = buf1(buf1(buf1(that)))
c.rework{
val ios = c.getAllIo.toList
ios.foreach{io =>
if(io.getName() == "clk"){
} else if(io.isInput){
io.setAsDirectionLess().allowDirectionLessIo
io := buf(in(cloneOf(io).setName(io.getName() + "_wrap")))
} else if(io.isOutput){
io.setAsDirectionLess().allowDirectionLessIo
out(cloneOf(io).setName(io.getName() + "_wrap")) := buf(io)
} else ???
}
}
c
}
def xorOutputs[T <: Component](c : T, cd : ClockDomain = ClockDomain.current): T ={
def buf1[T <: Data](that : T) = KeepAttribute(RegNext(that)).addAttribute("DONT_TOUCH")
def buf[T <: Data](that : T) = buf1(buf1(buf1(that)))
c.rework{
val outputs = c.getAllIo.toList.filter(_.isOutput)
val bools = outputs.flatMap(_.asBits.asBools)
outputs.foreach(_.setAsDirectionLess())
val agreg = out(B(bools).xorR)
}
c
}
def compactInputs[T <: Component](c: T, cd : ClockDomain = ClockDomain.current) : T = {
def buf1[T <: Data](that: T) = KeepAttribute(RegNext(that)).addAttribute("DONT_TOUCH")
def buf[T <: Data](that: T) = buf1(buf1(buf1(that)))
c.rework {
cd {
val inputs = c.getAllIo.toList.filter(_.isInput).filter(_.getBitsWidth > 1)
inputs.foreach(_.setAsDirectionLess())
var ptr = in(Bits(1 bits))
for (pin <- inputs; bitId <- 0 until widthOf(pin)) {
ptr = buf(ptr)
pin.assignFromBits(ptr, bitId, 1 bits)
}
}
}
c
}
}
object Bench {
def apply(rtls : Seq[Rtl], targets : Seq[Target], workspacesRoot : String = sys.env.getOrElse("SPINAL_BENCH_WORKSPACE", null)): Unit ={
import scala.concurrent.ExecutionContext
implicit val ec = ExecutionContext.fromExecutorService(
new ForkJoinPool(Math.max(1, sys.env.getOrElse("SPINAL_BENCH_THREAD_COUNT", SimManager.cpuCount/4 toString).toInt), ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, true)
)
val results = (for (rtl <- rtls) yield {
(rtl -> (for (target <- targets) yield {
val ret = (target -> Future{target.synthesise(rtl, workspacesRoot + rtl.getName().replace(" ", "") + "_" + target.getFamilyName().replace(" ", ""))})
// Thread.sleep(8000)
ret
}).toMap)
}).toMap
for (rtl <- rtls) {
for (target <- Random.shuffle(targets)) {
Await.ready(results(rtl)(target), Duration.Inf)
}
}
val targetNameLengthMax = targets.map(_.getFamilyName().size).max
for (rtl <- rtls) {
println(s"${rtl.getName()} ->")
for (target <- targets) {
try{
val report = results(rtl)(target).value.get.get
val name = target.getFamilyName()
println(s"- ${name}${" " * (targetNameLengthMax-name.size)} -> ${(report.getFMax / 1e6).toInt} Mhz ${report.getArea()}")
} catch {
case t : Throwable => println(s"${target.getFamilyName()} -> FAILED")
}
}
}
}
//Demo
def main(args: Array[String]) {
val fifo128 = new Rtl {
override def getName(): String = "Fifo 128"
override def getRtlPath(): String = "fifo128.v"
SpinalVerilog({
StreamFifo(Bits(32 bits), 128).setDefinitionName(getRtlPath().split("\\.").head)
})
}
val fifo1024 = new Rtl {
override def getName(): String = "Fifo 1024"
override def getRtlPath(): String = "fifo1024.v"
SpinalVerilog({
StreamFifo(Bits(32 bits), 1024).setDefinitionName(getRtlPath().split("\\.").head)
})
}
import spinal.lib._
val rtls = List(128, 1024).map(depth => Rtl(SpinalVerilog(new Component {
setDefinitionName(s"fifo$depth")
val push = slave Stream(Bits(32 bits))
val pop = master Stream(Bits(32 bits))
val f = new StreamFifo(Bits(32 bits), depth)
f.logic.ram.addAttribute("ram_style", "block")
f.io.push << push.halfPipe()
f.io.pop.halfPipe() >> pop
})))
// val targets = AlteraStdTargets(
// quartusCycloneIIPath = "D:/altera/13.0sp1/quartus/bin64",
// quartusCycloneIVPath = "D:/altera_lite/15.1/quartus/bin64",
// quartusCycloneVPath = "D:/altera_lite/15.1/quartus/bin64"
// ) ++ XilinxStdTargets(
// vivadoArtix7Path = "E:\\Xilinx\\Vivado\\2016.3\\bin"
// )
val targets = XilinxStdTargets() ++ AlteraStdTargets()
Bench(rtls, targets)
/*
fifo128 ->
Artix 7 -> 242 Mhz 23 LUT 50 FF
Artix 7 -> 335 Mhz 32 LUT 50 FF
Cyclone V -> 216 Mhz 23 ALMs
Cyclone IV -> 219 Mhz 30 LUT 50 FF
fifo1024 ->
Artix 7 -> 195 Mhz 36 LUT 56 FF
Artix 7 -> 263 Mhz 45 LUT 56 FF
Cyclone V -> 195 Mhz 26 ALMs
Cyclone IV -> 205 Mhz 40 LUT 56 FF
fifo128 ->
Artix 7 -> 243 Mhz 29 LUT 50 FF
Artix 7 -> 354 Mhz 38 LUT 50 FF
Cyclone V -> 249 Mhz 30 ALMs
Cyclone IV -> 250 Mhz 51 LUT 50 FF
fifo1024 ->
Artix 7 -> 240 Mhz 41 LUT 56 FF
Artix 7 -> 285 Mhz 48 LUT 56 FF
Cyclone V -> 216 Mhz 41 ALMs
Cyclone IV -> 217 Mhz 68 LUT 56 FF
fifo128 ->
Artix 7 -> 248 Mhz 32 LUT 63 FF
Artix 7 -> 357 Mhz 37 LUT 63 FF
Cyclone V -> 275 Mhz 30 ALMs
Cyclone IV -> 250 Mhz 49 LUT 63 FF
fifo1024 ->
Artix 7 -> 251 Mhz 41 LUT 75 FF
Artix 7 -> 296 Mhz 48 LUT 75 FF
Cyclone V -> 230 Mhz 39 ALMs
Cyclone IV -> 227 Mhz 68 LUT 75 FF
fifo128 ->
Artix 7 -> 374 Mhz 23 LUT 51 FF
Artix 7 -> 415 Mhz 29 LUT 51 FF
Cyclone V -> 275 Mhz 23 ALMs
Cyclone IV -> 226 Mhz 72 LUT 195 FF
fifo1024 ->
Artix 7 -> 250 Mhz 29 LUT 57 FF
Artix 7 -> 347 Mhz 33 LUT 57 FF
Cyclone V -> 275 Mhz 26 ALMs
Cyclone IV -> 235 Mhz 82 LUT 207 FF
fifo128 ->
Artix 7 -> 297 Mhz 25 LUT 59 FF
Artix 7 -> 420 Mhz 31 LUT 59 FF
Cyclone V -> 275 Mhz 24 ALMs
Cyclone IV -> 243 Mhz 76 LUT 203 FF
fifo1024 ->
Artix 7 -> 265 Mhz 31 LUT 68 FF
Artix 7 -> 364 Mhz 33 LUT 68 FF
Cyclone V -> 275 Mhz 31 ALMs
Cyclone IV -> 234 Mhz 89 LUT 218 FF
X
fifo128 ->
Artix 7 -> 374 Mhz 83 LUT 228 FF
Artix 7 -> 444 Mhz 119 LUT 228 FF
Cyclone V -> 263 Mhz 87 ALMs
fifo1024 ->
Artix 7 -> 355 Mhz 98 LUT 237 FF
Artix 7 -> 435 Mhz 134 LUT 237 FF
Cyclone V -> 275 Mhz 92 ALMs
fifo128 ->
Artix 7 -> 437 Mhz 52 LUT 65 FF
Artix 7 -> 447 Mhz 59 LUT 65 FF
Cyclone V -> 275 Mhz 50 ALMs
fifo1024 ->
Artix 7 -> 382 Mhz 70 LUT 77 FF
Artix 7 -> 454 Mhz 79 LUT 77 FF
Cyclone V -> 275 Mhz 68 ALMs
*/
}
def compressIo[T <: Component](c : T) : T = {
c.rework{
var outputXor = False
for(output <- c.getOrdredNodeIo.filter(_.isOutput)){
output.setAsDirectionLess().allowDirectionLessIo
for(outputBit <- output.asBits.asBools){
outputXor \= outputXor ^ outputBit
}
}
outputXor.asOutput().setName("finalOutput")
}
c
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy