113 lines
3.5 KiB
Scala
113 lines
3.5 KiB
Scala
// See LICENSE for license details.
|
|
|
|
package barstools.tapeout.transforms.retime.test
|
|
|
|
import chisel3._
|
|
import chisel3.stage.{ChiselStage, ChiselGeneratorAnnotation}
|
|
import firrtl.{EmittedFirrtlCircuitAnnotation, EmittedFirrtlModuleAnnotation}
|
|
import barstools.tapeout.transforms.retime.RetimeLib
|
|
import firrtl.FileUtils
|
|
import logger.Logger
|
|
import org.scalatest.{FlatSpec, Matchers}
|
|
|
|
class RetimeSpec extends FlatSpec with Matchers {
|
|
def normalized(s: String): String = {
|
|
require(!s.contains("\n"))
|
|
s.replaceAll("\\s+", " ").trim
|
|
}
|
|
def uniqueDirName[T](gen: => T, name: String): String = {
|
|
val genClassName = gen.getClass.getName
|
|
name + genClassName.hashCode.abs
|
|
}
|
|
def getLowFirrtl[T <: RawModule](gen: () => T, extraArgs: Array[String] = Array.empty): String = {
|
|
// generate low firrtl
|
|
(new ChiselStage).execute(
|
|
Array("-X", "low") ++ extraArgs,
|
|
Seq(ChiselGeneratorAnnotation(gen))
|
|
).collect {
|
|
case EmittedFirrtlCircuitAnnotation(a) => a
|
|
case EmittedFirrtlModuleAnnotation(a) => a
|
|
}.map(_.value)
|
|
.mkString("")
|
|
}
|
|
|
|
|
|
behavior of "retime library"
|
|
|
|
it should "pass simple retime module annotation" in {
|
|
val gen = () => new RetimeModule
|
|
val dir = uniqueDirName(gen, "RetimeModule")
|
|
|
|
Logger.makeScope(Seq.empty) {
|
|
val captor = new Logger.OutputCaptor
|
|
Logger.setOutput(captor.printStream)
|
|
|
|
// generate low firrtl
|
|
val firrtl = getLowFirrtl(gen,
|
|
Array("-td", s"test_run_dir/$dir", "-foaf", s"test_run_dir/$dir/final", "--log-level", "info"))
|
|
|
|
firrtl.nonEmpty should be(true)
|
|
//Make sure we got the RetimeTransform scheduled
|
|
captor.getOutputAsString should include ("barstools.tapeout.transforms.retime.RetimeTransform")
|
|
}
|
|
|
|
val lines = FileUtils.getLines(s"test_run_dir/$dir/test_run_dir/$dir/final.anno.json")
|
|
.map(normalized)
|
|
.mkString("\n")
|
|
lines should include("barstools.tapeout.transforms.retime.RetimeAnnotation")
|
|
lines should include(""""target":"RetimeModule.RetimeModule"""")
|
|
}
|
|
|
|
it should "pass simple retime instance annotation" in {
|
|
val gen = () => new RetimeInstance
|
|
val dir = uniqueDirName(gen, "RetimeInstance")
|
|
|
|
Logger.makeScope(Seq.empty) {
|
|
val captor = new Logger.OutputCaptor
|
|
Logger.setOutput(captor.printStream)
|
|
|
|
// generate low firrtl
|
|
val firrtl = getLowFirrtl(gen,
|
|
Array("-td", s"test_run_dir/$dir", "-foaf", s"test_run_dir/$dir/final", "--log-level", "info"))
|
|
|
|
firrtl.nonEmpty should be(true)
|
|
//Make sure we got the RetimeTransform scheduled
|
|
captor.getOutputAsString should include ("barstools.tapeout.transforms.retime.RetimeTransform")
|
|
}
|
|
|
|
val lines = FileUtils.getLines(s"test_run_dir/$dir/test_run_dir/$dir/final.anno.json")
|
|
.map(normalized)
|
|
.mkString("\n")
|
|
lines should include("barstools.tapeout.transforms.retime.RetimeAnnotation")
|
|
lines should include(""""target":"RetimeInstance.MyModule"""")
|
|
}
|
|
}
|
|
|
|
class RetimeModule extends Module with RetimeLib {
|
|
val io = IO(new Bundle {
|
|
val in = Input(UInt(15.W))
|
|
val out = Output(UInt(15.W))
|
|
})
|
|
io.out := io.in
|
|
retime(this)
|
|
}
|
|
|
|
class MyModule extends Module with RetimeLib {
|
|
val io = IO(new Bundle {
|
|
val in = Input(UInt(15.W))
|
|
val out = Output(UInt(15.W))
|
|
})
|
|
io.out := io.in
|
|
}
|
|
|
|
class RetimeInstance extends Module with RetimeLib {
|
|
val io = IO(new Bundle {
|
|
val in = Input(UInt(15.W))
|
|
val out = Output(UInt(15.W))
|
|
})
|
|
val instance = Module(new MyModule)
|
|
retime(instance)
|
|
instance.io.in := io.in
|
|
io.out := instance.io.out
|
|
}
|