Tapeout (#4)
* remove outdated files * pulled resetinverter from dsptools + setup repo * fix some package names, misc. dsptools dependencies, typo in build.sbt, + circuitstate in resetinverter pass * add more comprehensive gitignore + license back in * create directory structure to match package structure * change package names to barstools.tapeout * settled on barstools.tapeout.transforms package * make directory + build structure more amenable for multiple sub projects
This commit is contained in:
65
tapeout/src/main/scala/transforms/ResetInverter.scala
Normal file
65
tapeout/src/main/scala/transforms/ResetInverter.scala
Normal file
@@ -0,0 +1,65 @@
|
||||
// See LICENSE for license details.
|
||||
|
||||
package barstools.tapeout.transforms
|
||||
|
||||
import chisel3.internal.InstanceId
|
||||
import firrtl.PrimOps.Not
|
||||
import firrtl.annotations.{Annotation, CircuitName, ModuleName, Named}
|
||||
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 ResetInverterAnnotation {
|
||||
def apply(target: ModuleName): Annotation = Annotation(target, classOf[ResetInverterTransform], "invert")
|
||||
def unapply(a: Annotation): Option[Named] = a match {
|
||||
case Annotation(m, t, "invert") if t == classOf[ResetInverterTransform] => Some(m)
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
|
||||
object ResetN extends Pass {
|
||||
def name: String = "ResetN"
|
||||
private val Bool = UIntType(IntWidth(1))
|
||||
// Only works on Modules with a Bool port named reset
|
||||
def invertReset(mod: Module): Module = {
|
||||
// Check that it actually has reset
|
||||
require(mod.ports.exists(p => p.name == "reset" && p.tpe == Bool),
|
||||
"Can only invert reset on a module with reset!")
|
||||
// Rename "reset" to "reset_n"
|
||||
val portsx = mod.ports map {
|
||||
case Port(info, "reset", Input, Bool) => Port(info, "reset_n", Input, Bool)
|
||||
case other => other
|
||||
}
|
||||
val newReset = DefNode(NoInfo, "reset", DoPrim(Not, Seq(Reference("reset_n", Bool)), Seq.empty, Bool))
|
||||
val bodyx = Block(Seq(newReset, mod.body))
|
||||
mod.copy(ports = portsx, body = bodyx)
|
||||
}
|
||||
|
||||
def run(c: Circuit): Circuit =
|
||||
c.copy(modules = c.modules map {
|
||||
case mod: Module if mod.name == c.main => invertReset(mod)
|
||||
case other => other
|
||||
})
|
||||
}
|
||||
|
||||
class ResetInverterTransform extends Transform {
|
||||
override def inputForm: CircuitForm = LowForm
|
||||
override def outputForm: CircuitForm = LowForm
|
||||
|
||||
override def execute(state: CircuitState): CircuitState = {
|
||||
getMyAnnotations(state) match {
|
||||
case Nil => CircuitState(state.circuit, LowForm)
|
||||
case Seq(ResetInverterAnnotation(ModuleName(state.circuit.main, CircuitName(_)))) =>
|
||||
CircuitState(ResetN.run(state.circuit), LowForm)
|
||||
case annotations =>
|
||||
throw new Exception(s"There should be only one InvertReset annotation: got ${annotations.mkString(" -- ")}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait ResetInverter {
|
||||
self: chisel3.Module =>
|
||||
def invert(component: InstanceId): Unit = {
|
||||
annotate(chisel3.experimental.ChiselAnnotation(component, classOf[ResetInverterTransform], "invert"))
|
||||
}
|
||||
}
|
||||
39
tapeout/src/test/scala/transforms/ResetInverterSpec.scala
Normal file
39
tapeout/src/test/scala/transforms/ResetInverterSpec.scala
Normal file
@@ -0,0 +1,39 @@
|
||||
// See LICENSE for license details.
|
||||
|
||||
package barstools.tapeout.transforms
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util.RegInit
|
||||
import firrtl._
|
||||
import org.scalatest.{FreeSpec, Matchers}
|
||||
|
||||
class ExampleModuleNeedsResetInverted extends Module with ResetInverter {
|
||||
val io = IO(new Bundle {
|
||||
val out = Output(UInt(32.W))
|
||||
})
|
||||
|
||||
val r = RegInit(0.U)
|
||||
|
||||
invert(this)
|
||||
}
|
||||
|
||||
class ResetNSpec extends FreeSpec with Matchers {
|
||||
|
||||
"Inverting reset needs to be done throughout module" in {
|
||||
val optionsManager = new ExecutionOptionsManager("dsptools") with HasChiselExecutionOptions with HasFirrtlOptions {
|
||||
firrtlOptions = firrtlOptions.copy(compilerName = "low")
|
||||
}
|
||||
chisel3.Driver.execute(optionsManager, () => new ExampleModuleNeedsResetInverted) match {
|
||||
case ChiselExecutionSuccess(_, chirrtl, Some(FirrtlExecutionSuccess(_, firrtl))) =>
|
||||
chirrtl should include ("input reset :")
|
||||
chirrtl should not include "input reset_n :"
|
||||
chirrtl should not include "node reset = not(reset_n)"
|
||||
|
||||
firrtl should include ("input reset_n :")
|
||||
firrtl should include ("node reset = not(reset_n)")
|
||||
firrtl should not include "input reset :"
|
||||
case _ =>
|
||||
// bad
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user