Added retime annotation
This commit is contained in:
45
tapeout/src/main/scala/transforms/retime/Retime.scala
Normal file
45
tapeout/src/main/scala/transforms/retime/Retime.scala
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
package barstools.tapeout.transforms.retime
|
||||||
|
|
||||||
|
import chisel3.internal.InstanceId
|
||||||
|
import firrtl.PrimOps.Not
|
||||||
|
import firrtl.annotations.{Annotation, CircuitName, ModuleName, Named, ComponentName}
|
||||||
|
import firrtl.ir.{Input, UIntType, IntWidth, Module, Port, DefNode, NoInfo, Reference, DoPrim, Block, Circuit}
|
||||||
|
import firrtl.passes.Pass
|
||||||
|
import firrtl.{CircuitForm, CircuitState, LowForm, Transform}
|
||||||
|
|
||||||
|
object RetimeAnnotation {
|
||||||
|
def apply(target: ModuleName): Annotation = Annotation(target, classOf[RetimeTransform], "retime")
|
||||||
|
def unapply(a: Annotation): Option[Named] = a match {
|
||||||
|
case Annotation(m, t, "retime") if t == classOf[RetimeTransform] => Some(m)
|
||||||
|
case _ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RetimeTransform extends Transform {
|
||||||
|
override def inputForm: CircuitForm = LowForm
|
||||||
|
override def outputForm: CircuitForm = LowForm
|
||||||
|
|
||||||
|
override def execute(state: CircuitState): CircuitState = {
|
||||||
|
getMyAnnotations(state) match {
|
||||||
|
case Nil => state
|
||||||
|
case seq => seq.foreach {
|
||||||
|
case RetimeAnnotation(ModuleName(module, CircuitName(_))) =>
|
||||||
|
logger.info(s"Retiming module $module")
|
||||||
|
case RetimeAnnotation(ComponentName(name, ModuleName(module, CircuitName(_)))) =>
|
||||||
|
logger.info(s"Retiming instance $module.$name")
|
||||||
|
case _ =>
|
||||||
|
throw new Exception(s"There should be RetimeAnnotations, got ${seq.mkString(" -- ")}")
|
||||||
|
}
|
||||||
|
state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait RetimeLib {
|
||||||
|
self: chisel3.Module =>
|
||||||
|
def retime(component: InstanceId): Unit = {
|
||||||
|
annotate(chisel3.experimental.ChiselAnnotation(component, classOf[RetimeTransform], "retime"))
|
||||||
|
}
|
||||||
|
}
|
||||||
71
tapeout/src/test/scala/transforms/retime/RetimeSpec.scala
Normal file
71
tapeout/src/test/scala/transforms/retime/RetimeSpec.scala
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
package barstools.tapeout.transforms.retime.test
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
import firrtl._
|
||||||
|
import org.scalatest.{FlatSpec, Matchers}
|
||||||
|
import chisel3.experimental._
|
||||||
|
import chisel3.util.HasBlackBoxInline
|
||||||
|
import chisel3.iotesters._
|
||||||
|
import barstools.tapeout.transforms.retime._
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
behavior of "retime library"
|
||||||
|
|
||||||
|
it should "pass simple retime module annotation" in {
|
||||||
|
val gen = () => new RetimeModule()
|
||||||
|
val dir = uniqueDirName(gen, "RetimeModule")
|
||||||
|
chisel3.Driver.execute(Array("-td", s"test_run_dir/$dir", "-foaf", s"test_run_dir/$dir/final.anno"), gen) shouldBe a [ChiselExecutionSuccess]
|
||||||
|
|
||||||
|
val lines = io.Source.fromFile(s"test_run_dir/$dir/final.anno").getLines().map(normalized).toSeq
|
||||||
|
lines should contain ("Annotation(ModuleName(RetimeModule,CircuitName(RetimeModule)),class barstools.tapeout.transforms.retime.RetimeTransform,retime)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(azidar): need to fix/add instance annotations
|
||||||
|
ignore should "pass simple retime instance annotation" in {
|
||||||
|
val gen = () => new RetimeInstance()
|
||||||
|
val dir = uniqueDirName(gen, "RetimeInstance")
|
||||||
|
chisel3.Driver.execute(Array("-td", s"test_run_dir/$dir", "-foaf", s"test_run_dir/$dir/final.anno"), gen) shouldBe a [ChiselExecutionSuccess]
|
||||||
|
|
||||||
|
val lines = io.Source.fromFile(s"test_run_dir/$dir/final.anno").getLines().map(normalized).toSeq
|
||||||
|
lines should contain ("Annotation(ComponentName(instance, ModuleName(RetimeInstance,CircuitName(RetimeInstance))),class barstools.tapeout.transforms.retime.RetimeTransform,retime)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user