diff options
Diffstat (limited to 'src')
5 files changed, 154 insertions, 132 deletions
diff --git a/src/main/scala/firrtl/passes/memlib/CreateMemoryAnnotations.scala b/src/main/scala/firrtl/passes/memlib/CreateMemoryAnnotations.scala index ce7eea5e..240c2c9a 100644 --- a/src/main/scala/firrtl/passes/memlib/CreateMemoryAnnotations.scala +++ b/src/main/scala/firrtl/passes/memlib/CreateMemoryAnnotations.scala @@ -4,26 +4,29 @@ package firrtl package passes package memlib +import firrtl.Utils.error import firrtl.stage.Forms -@deprecated("CreateMemoryAnnotations will not take reader: Option[YamlFileReader] as argument since 1.5.", "FIRRTL 1.4") -class CreateMemoryAnnotations(reader: Option[YamlFileReader]) extends Transform with DependencyAPIMigration { +import java.io.File + +class CreateMemoryAnnotations extends Transform with DependencyAPIMigration { override def prerequisites = Forms.MidForm override def optionalPrerequisites = Seq.empty override def optionalPrerequisiteOf = Forms.MidEmitters override def invalidates(a: Transform) = false - def execute(state: CircuitState): CircuitState = reader match { - case None => state - case Some(r) => - import CustomYAMLProtocol._ - val configs = r.parse[Config] - val oldAnnos = state.annotations - val (as, pins) = configs.foldLeft((oldAnnos, Seq.empty[String])) { - case ((annos, pins), config) => - (annos, pins :+ config.pin.name) - } - state.copy(annotations = PinAnnotation(pins.toSeq) +: as) + def execute(state: CircuitState): CircuitState = { + state.copy(annotations = state.annotations.flatMap { + case ReplSeqMemAnnotation(inputFileName, outputConfig) => + Seq(MemLibOutConfigFileAnnotation(outputConfig, Nil)) ++ { + if (inputFileName.isEmpty) None + else if (new File(inputFileName).exists) { + import CustomYAMLProtocol._ + Some(PinAnnotation(new YamlFileReader(inputFileName).parse[Config].map(_.pin.name))) + } else error("Input configuration file does not exist!") + } + case a => Seq(a) + }) } } diff --git a/src/main/scala/firrtl/passes/memlib/DumpMemoryAnnotations.scala b/src/main/scala/firrtl/passes/memlib/DumpMemoryAnnotations.scala new file mode 100644 index 00000000..5cc1e0bf --- /dev/null +++ b/src/main/scala/firrtl/passes/memlib/DumpMemoryAnnotations.scala @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: Apache-2.0 + +package firrtl +package passes +package memlib + +import firrtl.stage.Forms + +class DumpMemoryAnnotations extends Transform with DependencyAPIMigration { + + override def prerequisites = Forms.MidForm + override def optionalPrerequisites = Seq.empty + override def optionalPrerequisiteOf = Forms.MidEmitters + override def invalidates(a: Transform) = false + + def execute(state: CircuitState): CircuitState = { + state.copy(annotations = state.annotations.flatMap { + // convert and remove AnnotatedMemoriesAnnotation to CustomFileEmission + case AnnotatedMemoriesAnnotation(annotatedMemories) => + state.annotations.collect { + case a: MemLibOutConfigFileAnnotation => + a.copy(annotatedMemories = annotatedMemories) + // todo convert xxx to verilogs here. + } + case MemLibOutConfigFileAnnotation(_, Nil) => Nil + case a => Seq(a) + }) + } +} diff --git a/src/main/scala/firrtl/passes/memlib/ReplaceMemMacros.scala b/src/main/scala/firrtl/passes/memlib/ReplaceMemMacros.scala index bb2bed33..4b43118b 100644 --- a/src/main/scala/firrtl/passes/memlib/ReplaceMemMacros.scala +++ b/src/main/scala/firrtl/passes/memlib/ReplaceMemMacros.scala @@ -3,15 +3,17 @@ package firrtl.passes package memlib -import firrtl._ -import firrtl.ir._ -import firrtl.Utils._ import firrtl.Mappers._ -import MemPortUtils.{MemPortMap, Modules} -import MemTransformUtils._ +import firrtl.Utils._ +import firrtl._ import firrtl.annotations._ +import firrtl.ir._ +import firrtl.passes.MemPortUtils.{MemPortMap, Modules} +import firrtl.passes.memlib.MemTransformUtils._ +import firrtl.passes.wiring._ import firrtl.stage.Forms -import wiring._ + +import scala.collection.mutable.ListBuffer /** Annotates the name of the pins to add for WiringTransform */ case class PinAnnotation(pins: Seq[String]) extends NoTargetAnnotation @@ -24,9 +26,7 @@ object ReplaceMemMacros { * This will not generate wmask ports if not needed. * Creates the minimum # of black boxes needed by the design. */ -@deprecated("ReplaceMemMacros will not take writer: ConfWriter as argument since 1.5.", "FIRRTL 1.4") -class ReplaceMemMacros(writer: ConfWriter) extends Transform with DependencyAPIMigration { - +class ReplaceMemMacros extends Transform with DependencyAPIMigration { override def prerequisites = Forms.MidForm override def optionalPrerequisites = Seq.empty override def optionalPrerequisiteOf = Forms.MidEmitters @@ -122,15 +122,13 @@ class ReplaceMemMacros(writer: ConfWriter) extends Transform with DependencyAPIM }) ) - @deprecated("memToBundle will become private in 1.5.", "FIRRTL 1.4") - def memToBundle(s: DefAnnotatedMemory) = BundleType( + private def memToBundle(s: DefAnnotatedMemory) = BundleType( s.readers.map(Field(_, Flip, rPortToBundle(s))) ++ s.writers.map(Field(_, Flip, wPortToBundle(s))) ++ s.readwriters.map(Field(_, Flip, rwPortToBundle(s))) ) - @deprecated("memToFlattenBundle will become private in 1.5.", "FIRRTL 1.4") - def memToFlattenBundle(s: DefAnnotatedMemory) = BundleType( + private def memToFlattenBundle(s: DefAnnotatedMemory) = BundleType( s.readers.map(Field(_, Flip, rPortToFlattenBundle(s))) ++ s.writers.map(Field(_, Flip, wPortToFlattenBundle(s))) ++ s.readwriters.map(Field(_, Flip, rwPortToFlattenBundle(s))) @@ -140,8 +138,11 @@ class ReplaceMemMacros(writer: ConfWriter) extends Transform with DependencyAPIM * The wrapper module has the same type as the memory it replaces * The external module */ - @deprecated("createMemModule will become private in 1.5.", "FIRRTL 1.4") - def createMemModule(m: DefAnnotatedMemory, wrapperName: String): Seq[DefModule] = { + private def createMemModule( + m: DefAnnotatedMemory, + wrapperName: String, + annotatedMemoriesBuffer: ListBuffer[DefAnnotatedMemory] + ): Seq[DefModule] = { assert(m.dataType != UnknownType) val wrapperIoType = memToBundle(m) val wrapperIoPorts = wrapperIoType.fields.map(f => Port(NoInfo, f.name, Input, f.tpe)) @@ -161,29 +162,25 @@ class ReplaceMemMacros(writer: ConfWriter) extends Transform with DependencyAPIM // TODO: Annotate? -- use actual annotation map // add to conf file - writer.append(m) + annotatedMemoriesBuffer += m Seq(bb, wrapper) } // TODO(shunshou): get rid of copy pasta // Connects the clk, en, and addr fields from the wrapperPort to the bbPort - @deprecated("defaultConnects will become private in 1.5.", "FIRRTL 1.4") - def defaultConnects(wrapperPort: WRef, bbPort: WSubField): Seq[Connect] = + private def defaultConnects(wrapperPort: WRef, bbPort: WSubField): Seq[Connect] = Seq("clk", "en", "addr").map(f => connectFields(bbPort, f, wrapperPort, f)) // Generates mask bits (concatenates an aggregate to ground type) // depending on mask granularity (# bits = data width / mask granularity) - @deprecated("maskBits will become private in 1.5.", "FIRRTL 1.4") - def maskBits(mask: WSubField, dataType: Type, fillMask: Boolean): Expression = + private def maskBits(mask: WSubField, dataType: Type, fillMask: Boolean): Expression = if (fillMask) toBitMask(mask, dataType) else toBits(mask) - @deprecated("adaptReader will become private in 1.5.", "FIRRTL 1.4") - def adaptReader(wrapperPort: WRef, bbPort: WSubField): Seq[Statement] = + private def adaptReader(wrapperPort: WRef, bbPort: WSubField): Seq[Statement] = defaultConnects(wrapperPort, bbPort) :+ fromBits(WSubField(wrapperPort, "data"), WSubField(bbPort, "data")) - @deprecated("adaptWriter will become private in 1.5.", "FIRRTL 1.4") - def adaptWriter(wrapperPort: WRef, bbPort: WSubField, hasMask: Boolean, fillMask: Boolean): Seq[Statement] = { + private def adaptWriter(wrapperPort: WRef, bbPort: WSubField, hasMask: Boolean, fillMask: Boolean): Seq[Statement] = { val wrapperData = WSubField(wrapperPort, "data") val defaultSeq = defaultConnects(wrapperPort, bbPort) :+ Connect(NoInfo, WSubField(bbPort, "data"), toBits(wrapperData)) @@ -198,8 +195,12 @@ class ReplaceMemMacros(writer: ConfWriter) extends Transform with DependencyAPIM } } - @deprecated("adaptReadWriter will become private in 1.5.", "FIRRTL 1.4") - def adaptReadWriter(wrapperPort: WRef, bbPort: WSubField, hasMask: Boolean, fillMask: Boolean): Seq[Statement] = { + private def adaptReadWriter( + wrapperPort: WRef, + bbPort: WSubField, + hasMask: Boolean, + fillMask: Boolean + ): Seq[Statement] = { val wrapperWData = WSubField(wrapperPort, "wdata") val defaultSeq = defaultConnects(wrapperPort, bbPort) ++ Seq( fromBits(WSubField(wrapperPort, "rdata"), WSubField(bbPort, "rdata")), @@ -221,8 +222,7 @@ class ReplaceMemMacros(writer: ConfWriter) extends Transform with DependencyAPIM private type NameMap = collection.mutable.HashMap[(String, String), String] /** Construct NameMap by assigning unique names for each memory blackbox */ - @deprecated("constructNameMap will become private in 1.5.", "FIRRTL 1.4") - def constructNameMap(namespace: Namespace, nameMap: NameMap, mname: String)(s: Statement): Statement = { + private def constructNameMap(namespace: Namespace, nameMap: NameMap, mname: String)(s: Statement): Statement = { s match { case m: DefAnnotatedMemory => m.memRef match { @@ -234,14 +234,14 @@ class ReplaceMemMacros(writer: ConfWriter) extends Transform with DependencyAPIM s.map(constructNameMap(namespace, nameMap, mname)) } - @deprecated("updateMemStmts will be private in 1.5.", "FIRRTL 1.4") - def updateMemStmts( - namespace: Namespace, - nameMap: NameMap, - mname: String, - memPortMap: MemPortMap, - memMods: Modules - )(s: Statement + private def updateMemStmts( + namespace: Namespace, + nameMap: NameMap, + mname: String, + memPortMap: MemPortMap, + memMods: Modules, + annotatedMemoriesBuffer: ListBuffer[DefAnnotatedMemory] + )(s: Statement ): Statement = s match { case m: DefAnnotatedMemory => if (m.maskGran.isEmpty) { @@ -254,42 +254,49 @@ class ReplaceMemMacros(writer: ConfWriter) extends Transform with DependencyAPIM val newWrapperName = nameMap(mname -> m.name) val newMemBBName = namespace.newName(s"${newWrapperName}_ext") val newMem = m.copy(name = newMemBBName) - memMods ++= createMemModule(newMem, newWrapperName) + memMods ++= createMemModule(newMem, newWrapperName, annotatedMemoriesBuffer) WDefInstance(m.info, m.name, newWrapperName, UnknownType) case Some((module, mem)) => WDefInstance(m.info, m.name, nameMap(module -> mem), UnknownType) } - case sx => sx.map(updateMemStmts(namespace, nameMap, mname, memPortMap, memMods)) + case sx => sx.map(updateMemStmts(namespace, nameMap, mname, memPortMap, memMods, annotatedMemoriesBuffer)) } - @deprecated("updateMemMods will be private in 1.5.", "FIRRTL 1.4") - def updateMemMods(namespace: Namespace, nameMap: NameMap, memMods: Modules)(m: DefModule) = { + private def updateMemMods( + namespace: Namespace, + nameMap: NameMap, + memMods: Modules, + annotatedMemoriesBuffer: ListBuffer[DefAnnotatedMemory] + )(m: DefModule + ) = { val memPortMap = new MemPortMap - (m.map(updateMemStmts(namespace, nameMap, m.name, memPortMap, memMods)) + (m.map(updateMemStmts(namespace, nameMap, m.name, memPortMap, memMods, annotatedMemoriesBuffer)) .map(updateStmtRefs(memPortMap))) } def execute(state: CircuitState): CircuitState = { + val annotatedMemoriesBuffer: collection.mutable.ListBuffer[DefAnnotatedMemory] = ListBuffer[DefAnnotatedMemory]() val c = state.circuit val namespace = Namespace(c) val memMods = new Modules val nameMap = new NameMap c.modules.map(m => m.map(constructNameMap(namespace, nameMap, m.name))) - val modules = c.modules.map(updateMemMods(namespace, nameMap, memMods)) - // print conf - writer.serialize() - val pannos = state.annotations.collect { case a: PinAnnotation => a } - val pins = pannos match { - case Seq() => Nil - case Seq(PinAnnotation(pins)) => pins - case _ => throwInternalError("Something went wrong") - } - val annos = pins.foldLeft(Seq[Annotation]()) { (seq, pin) => - seq ++ memMods.collect { - case m: ExtModule => SinkAnnotation(ModuleName(m.name, CircuitName(c.main)), pin) - } - } ++ state.annotations - state.copy(circuit = c.copy(modules = modules ++ memMods), annotations = annos) + val modules = c.modules.map(updateMemMods(namespace, nameMap, memMods, annotatedMemoriesBuffer)) + state.copy( + circuit = c.copy(modules = modules ++ memMods), + annotations = + state.annotations ++ + (state.annotations.collectFirst { case a: PinAnnotation => a } match { + case None => Nil + case Some(PinAnnotation(pins)) => + pins.foldLeft(Seq[Annotation]()) { (seq, pin) => + seq ++ memMods.collect { + case m: ExtModule => SinkAnnotation(ModuleName(m.name, CircuitName(c.main)), pin) + } + } + }) :+ + AnnotatedMemoriesAnnotation(annotatedMemoriesBuffer.toList) + ) } } diff --git a/src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala b/src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala index 515ac691..f9df27a7 100644 --- a/src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala +++ b/src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala @@ -3,14 +3,15 @@ package firrtl.passes package memlib +import firrtl.Utils.error import firrtl._ import firrtl.annotations._ -import firrtl.options.{HasShellOptions, ShellOption} -import Utils.error -import java.io.{CharArrayWriter, File, PrintWriter} -import wiring._ +import firrtl.options.{CustomFileEmission, HasShellOptions, ShellOption} +import firrtl.passes.wiring._ import firrtl.stage.{Forms, RunFirrtlTransformAnnotation} +import java.io.{CharArrayWriter, PrintWriter} + sealed trait PassOption case object InputConfigFileName extends PassOption case object OutputConfigFileName extends PassOption @@ -43,15 +44,20 @@ object PassConfigUtil { } } -@deprecated("ConfWriter will be removed in 1.5.", "FIRRTL 1.4") -class ConfWriter(filename: String) { - val outputBuffer = new CharArrayWriter - def append(m: DefAnnotatedMemory) = { - // legacy - // assert that we don't overflow going from BigInt to Int conversion +case class ReplSeqMemAnnotation(inputFileName: String, outputConfig: String) extends NoTargetAnnotation + +/** Generate conf file for a sequence of [[DefAnnotatedMemory]] + * @note file already has its suffix adding by `--replSeqMem` + */ +case class MemLibOutConfigFileAnnotation(file: String, annotatedMemories: Seq[DefAnnotatedMemory]) + extends NoTargetAnnotation + with CustomFileEmission { + def baseFileName(annotations: AnnotationSeq) = file + def suffix = None + def getBytes = annotatedMemories.map { m => require(bitWidth(m.dataType) <= Int.MaxValue) - m.maskGran.foreach { case x => require(x <= Int.MaxValue) } - val conf = MemConf( + m.maskGran.foreach(x => require(x <= Int.MaxValue)) + MemConf( m.name, m.depth, bitWidth(m.dataType).toInt, @@ -59,17 +65,12 @@ class ConfWriter(filename: String) { m.writers.length, m.readwriters.length, m.maskGran.map(_.toInt) - ) - outputBuffer.append(conf.toString) - } - def serialize() = { - val outputFile = new PrintWriter(filename) - outputFile.write(outputBuffer.toString) - outputFile.close() - } + ).toString + }.mkString("\n").getBytes } -case class ReplSeqMemAnnotation(inputFileName: String, outputConfig: String) extends NoTargetAnnotation +private[memlib] case class AnnotatedMemoriesAnnotation(annotatedMemories: List[DefAnnotatedMemory]) + extends NoTargetAnnotation object ReplSeqMemAnnotation { def parse(t: String): ReplSeqMemAnnotation = { @@ -112,8 +113,7 @@ class SimpleTransform(p: Pass, form: CircuitForm) extends Transform { class SimpleMidTransform(p: Pass) extends SimpleTransform(p, MidForm) // SimpleRun instead of PassBased because of the arguments to passSeq -@deprecated("Migrate to a SeqTransform. API will be changed in 1.5.", "FIRRTL 1.4") -class ReplSeqMem extends Transform with HasShellOptions with DependencyAPIMigration { +class ReplSeqMem extends SeqTransform with HasShellOptions with DependencyAPIMigration { override def prerequisites = Forms.MidForm override def optionalPrerequisites = Seq.empty @@ -134,33 +134,16 @@ class ReplSeqMem extends Transform with HasShellOptions with DependencyAPIMigrat ) ) - @deprecated("API will be replaced with a val in 1.5.", "FIRRTL 1.4") - def transforms(inConfigFile: Option[YamlFileReader], outConfigFile: ConfWriter): Seq[Transform] = + val transforms: Seq[Transform] = Seq( new SimpleMidTransform(Legalize), new SimpleMidTransform(ToMemIR), new SimpleMidTransform(ResolveMaskGranularity), new SimpleMidTransform(RenameAnnotatedMemoryPorts), + new CreateMemoryAnnotations, new ResolveMemoryReference, - new CreateMemoryAnnotations(inConfigFile), - new ReplaceMemMacros(outConfigFile), - new WiringTransform + new ReplaceMemMacros, + new WiringTransform, + new DumpMemoryAnnotations ) - - @deprecated("API will be removed in 1.5.", "FIRRTL 1.4") - def execute(state: CircuitState): CircuitState = { - val annos = state.annotations.collect { case a: ReplSeqMemAnnotation => a } - annos match { - case Nil => state // Do nothing if there are no annotations - case Seq(ReplSeqMemAnnotation(inputFileName, outputConfig)) => - val inConfigFile = { - if (inputFileName.isEmpty) None - else if (new File(inputFileName).exists) Some(new YamlFileReader(inputFileName)) - else error("Input configuration file does not exist!") - } - val outConfigFile = new ConfWriter(outputConfig) - transforms(inConfigFile, outConfigFile).foldLeft(state) { (in, xform) => xform.runTransform(in) } - case _ => error("Unexpected transform annotation") - } - } } diff --git a/src/test/scala/firrtlTests/ReplSeqMemTests.scala b/src/test/scala/firrtlTests/ReplSeqMemTests.scala index 84709a21..4e00cb3a 100644 --- a/src/test/scala/firrtlTests/ReplSeqMemTests.scala +++ b/src/test/scala/firrtlTests/ReplSeqMemTests.scala @@ -3,14 +3,13 @@ package firrtlTests import firrtl._ +import firrtl.annotations._ import firrtl.ir._ import firrtl.passes._ -import firrtl.transforms._ import firrtl.passes.memlib._ -import firrtl.FileUtils +import firrtl.testutils.FirrtlCheckers._ import firrtl.testutils._ -import annotations._ -import FirrtlCheckers._ +import firrtl.transforms._ class ReplSeqMemSpec extends SimpleTransformSpec { def emitter = new LowFirrtlEmitter @@ -30,10 +29,11 @@ class ReplSeqMemSpec extends SimpleTransformSpec { } ) - @deprecated("API will be changed in 1.5.", "FIRRTL 1.4") - def checkMemConf(filename: String, mems: Set[MemConf]) { + def checkMemConf(circuitState: CircuitState, mems: Set[MemConf]) { // Read the mem conf - val text = FileUtils.getText(filename) + val text = circuitState.annotations.collectFirst { + case a: MemLibOutConfigFileAnnotation => a.getBytes.map(_.toChar).mkString + }.get // Verify that this does not throw an exception val fromConf = MemConf.fromString(text) // Verify the mems in the conf are the same as the expected ones @@ -75,7 +75,7 @@ circuit Top : // Check correctness of firrtl parse(res.getEmittedCircuit.value) // Check the emitted conf - checkMemConf(confLoc, mems) + checkMemConf(res, mems) (new java.io.File(confLoc)).delete() } @@ -100,7 +100,7 @@ circuit Top : // Check correctness of firrtl parse(res.getEmittedCircuit.value) // Check the emitted conf - checkMemConf(confLoc, mems) + checkMemConf(res, mems) (new java.io.File(confLoc)).delete() } @@ -128,7 +128,7 @@ circuit CustomMemory : // Check correctness of firrtl parse(res.getEmittedCircuit.value) // Check the emitted conf - checkMemConf(confLoc, mems) + checkMemConf(res, mems) (new java.io.File(confLoc)).delete() } @@ -156,7 +156,7 @@ circuit CustomMemory : // Check correctness of firrtl parse(res.getEmittedCircuit.value) // Check the emitted conf - checkMemConf(confLoc, mems) + checkMemConf(res, mems) (new java.io.File(confLoc)).delete() } @@ -245,7 +245,7 @@ circuit CustomMemory : } numExtMods should be(2) // Check the emitted conf - checkMemConf(confLoc, mems) + checkMemConf(res, mems) (new java.io.File(confLoc)).delete() } @@ -292,7 +292,7 @@ circuit CustomMemory : } numExtMods should be(2) // Check the emitted conf - checkMemConf(confLoc, mems) + checkMemConf(res, mems) (new java.io.File(confLoc)).delete() } @@ -354,7 +354,7 @@ circuit CustomMemory : // would be 3 ExtModules numExtMods should be(2) // Check the emitted conf - checkMemConf(confLoc, mems) + checkMemConf(res, mems) (new java.io.File(confLoc)).delete() } @@ -414,7 +414,7 @@ circuit CustomMemory : val res = compileAndEmit(CircuitState(parse(input), ChirrtlForm, annos)) res.getEmittedCircuit.value shouldNot include("mask") // Check the emitted conf - checkMemConf(confLoc, mems) + checkMemConf(res, mems) (new java.io.File(confLoc)).delete() } @@ -444,7 +444,7 @@ circuit CustomMemory : res should containLine("mem.W0_mask_0 <= validif(io_en, io_mask_0)") res should containLine("mem.W0_mask_1 <= validif(io_en, io_mask_1)") // Check the emitted conf - checkMemConf(confLoc, mems) + checkMemConf(res, mems) (new java.io.File(confLoc)).delete() } @@ -478,7 +478,7 @@ circuit CustomMemory : res should containLine("mem.RW0_wmask_0 <= validif(io_en, io_mask_0)") res should containLine("mem.RW0_wmask_1 <= validif(io_en, io_mask_1)") // Check the emitted conf - checkMemConf(confLoc, mems) + checkMemConf(res, mems) (new java.io.File(confLoc)).delete() } @@ -499,7 +499,7 @@ circuit NoMemsHere : val annos = Seq(ReplSeqMemAnnotation.parse("-c:CustomMemory:-o:" + confLoc), InferReadWriteAnnotation) val res = compileAndEmit(CircuitState(parse(input), ChirrtlForm, annos)) // Check the emitted conf - checkMemConf(confLoc, mems) + checkMemConf(res, mems) (new java.io.File(confLoc)).delete() } |
