82 lines
2.6 KiB
Scala
82 lines
2.6 KiB
Scala
// See LICENSE for license details
|
|
|
|
package barstools.tapeout.transforms
|
|
|
|
import chisel3._
|
|
import chisel3.experimental.ChiselAnnotation
|
|
import chisel3.util._
|
|
import chisel3.testers.BasicTester
|
|
import chisel3.experimental.{Analog, attach}
|
|
import firrtl.ir.{AnalogType, Circuit, DefModule, Expression, HasName, Port, Statement, Type}
|
|
import firrtl.{CircuitForm, CircuitState, LowForm, Transform}
|
|
import firrtl.annotations.{Annotation, ModuleName, Named, ComponentName}
|
|
import firrtl.Mappers._
|
|
|
|
object AnalogRenamerAnnotation {
|
|
def apply(target: Named, value: String): Annotation =
|
|
Annotation(target, classOf[AnalogRenamer], value)
|
|
|
|
def unapply(a: Annotation): Option[(ComponentName, String)] = a match {
|
|
case Annotation(named, t, value) if t == classOf[AnalogRenamer] => named match {
|
|
case c: ComponentName => Some((c, value))
|
|
case _ => None
|
|
}
|
|
case _ => None
|
|
}
|
|
}
|
|
|
|
class AnalogRenamer 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 annos =>
|
|
val analogs = annos.collect { case AnalogRenamerAnnotation(ana, name) => (ana, name) }
|
|
state.copy(circuit = run(state.circuit, analogs))
|
|
}
|
|
}
|
|
|
|
def run(circuit: Circuit, annos: Seq[(ComponentName, String)]): Circuit = {
|
|
circuit map walkModule(annos)
|
|
}
|
|
def walkModule(annos: Seq[(ComponentName, String)])(m: DefModule): DefModule = {
|
|
val filteredAnnos = Map(annos.filter(a => a._1.module.name == m.name).map {
|
|
case (c, s) => c.name.replace(".", "_") -> s
|
|
}: _*)
|
|
m map walkStatement(filteredAnnos) map walkPort(filteredAnnos)
|
|
}
|
|
def walkStatement(annos: Map[String, String])(s: Statement): Statement = {
|
|
s map walkExpression(annos)
|
|
}
|
|
def walkPort(annos: Map[String, String])(p: Port): Port = {
|
|
if (annos.contains(p.name)) {
|
|
updateAnalogVerilog(annos(p.name))(p.tpe)
|
|
}
|
|
p
|
|
}
|
|
def walkExpression(annos: Map[String, String])(e: Expression): Expression = {
|
|
e match {
|
|
case h: HasName =>
|
|
if (annos.contains(h.name)) e mapType updateAnalogVerilog(annos(h.name))
|
|
case _ =>
|
|
}
|
|
e
|
|
}
|
|
def updateAnalogVerilog(value: String)(tpe: Type): Type = {
|
|
tpe match {
|
|
case a: AnalogType =>
|
|
a.verilogTpe = value
|
|
a
|
|
case t => t
|
|
}
|
|
}
|
|
}
|
|
|
|
trait AnalogAnnotator { self: Module =>
|
|
def renameAnalog(component: Analog, value: String): Unit = {
|
|
annotate(ChiselAnnotation(component, classOf[AnalogRenamer], value))
|
|
}
|
|
}
|