diff --git a/src/main/scala/barstools/macros/CostMetric.scala b/src/main/scala/barstools/macros/CostMetric.scala index 8b0d0413..647889d3 100644 --- a/src/main/scala/barstools/macros/CostMetric.scala +++ b/src/main/scala/barstools/macros/CostMetric.scala @@ -44,7 +44,7 @@ trait CostMetricCompanion { object OldMetric extends CostMetric with CostMetricCompanion { override def cost(mem: Macro, lib: Macro): Option[Double] = { /* Palmer: A quick cost function (that must be kept in sync with - * memory_cost()) that attempts to avoid compiling unncessary + * memory_cost()) that attempts to avoid compiling unnecessary * memories. This is a lower bound on the cost of compiling a * memory: it assumes 100% bit-cell utilization when mapping. */ // val cost = 100 * (mem.depth * mem.width) / (lib.depth * lib.width) + @@ -52,9 +52,9 @@ object OldMetric extends CostMetric with CostMetricCompanion { ??? } - override def commandLineParams = Map() - override def name = "OldMetric" - override def construct(m: Map[String, String]) = OldMetric + override def commandLineParams() = Map.empty[String, String] + override def name() = "OldMetric" + override def construct(m: Map[String, String]): CostMetric = OldMetric } /** An external cost function. @@ -79,7 +79,7 @@ class ExternalMetric(path: String) extends CostMetric { writeMacroToPath(Some(libFile.getAbsolutePath), lib.src) // !! executes the given command - val result: String = (s"${path} ${memFile.getAbsolutePath} ${libFile.getAbsolutePath}" !!).trim + val result: String = (s"$path ${memFile.getAbsolutePath} ${libFile.getAbsolutePath}" !!).trim // Remove temporary files. memFile.delete() @@ -88,19 +88,19 @@ class ExternalMetric(path: String) extends CostMetric { try { Some(result.toDouble) } catch { - case e: NumberFormatException => None + case _: NumberFormatException => None } } - override def commandLineParams = Map("path" -> path) - override def name = ExternalMetric.name + override def commandLineParams() = Map("path" -> path) + override def name(): String = ExternalMetric.name() } object ExternalMetric extends CostMetricCompanion { - override def name = "ExternalMetric" + override def name() = "ExternalMetric" /** Construct this cost metric from a command line mapping. */ - override def construct(m: Map[String, String]) = { + override def construct(m: Map[String, String]): ExternalMetric = { val pathOption = m.get("path") pathOption match { case Some(path: String) => new ExternalMetric(path) @@ -113,25 +113,24 @@ object ExternalMetric extends CostMetricCompanion { // TODO: write tests for this function to make sure it selects the right things object DefaultMetric extends CostMetric with CostMetricCompanion { override def cost(mem: Macro, lib: Macro): Option[Double] = { - val memMask = mem.src.ports.map(_.maskGran).find(_.isDefined).map(_.get) - val libMask = lib.src.ports.map(_.maskGran).find(_.isDefined).map(_.get) + val memMask = mem.src.ports.map(_.maskGran).find(_.isDefined).flatten + val libMask = lib.src.ports.map(_.maskGran).find(_.isDefined).flatten val memWidth = (memMask, libMask) match { case (None, _) => mem.src.width case (Some(p), None) => (mem.src.width / p) * math.ceil( p.toDouble / lib.src.width ) * lib.src.width //We map the mask to distinct memories - case (Some(p), Some(m)) => { - if (m <= p) (mem.src.width / p) * math.ceil(p.toDouble / m) * m //Using multiple m's to create a p (integeraly) + case (Some(p), Some(m)) => + if (m <= p) (mem.src.width / p) * math.ceil(p.toDouble / m) * m //Using multiple m's to create a p (integrally) else (mem.src.width / p) * m //Waste the extra maskbits - } } val maskPenalty = (memMask, libMask) match { - case (None, Some(m)) => 0.001 + case (None, Some(_)) => 0.001 case (_, _) => 0 } val depthCost = math.ceil(mem.src.depth.toDouble / lib.src.depth.toDouble) - val widthCost = math.ceil(memWidth.toDouble / lib.src.width.toDouble) + val widthCost = math.ceil(memWidth / lib.src.width.toDouble) val bitsCost = (lib.src.depth * lib.src.width).toDouble // Fraction of wasted bits plus const per mem val requestedBits = (mem.src.depth * mem.src.width).toDouble @@ -141,9 +140,9 @@ object DefaultMetric extends CostMetric with CostMetricCompanion { Some(1.0 * bitsWasted / requestedBits + costPerInst + maskPenalty) } - override def commandLineParams = Map() - override def name = "DefaultMetric" - override def construct(m: Map[String, String]) = DefaultMetric + override def commandLineParams() = Map.empty[String, String] + override def name() = "DefaultMetric" + override def construct(m: Map[String, String]): CostMetric = DefaultMetric } object MacroCompilerUtil { @@ -156,11 +155,11 @@ object MacroCompilerUtil { * Used to pass structured values through as an annotation. */ def objToString(o: Serializable): String = { - val baos: ByteArrayOutputStream = new ByteArrayOutputStream - val oos: ObjectOutputStream = new ObjectOutputStream(baos) - oos.writeObject(o) - oos.close() - return Base64.getEncoder.encodeToString(baos.toByteArray) + val byteOutput: ByteArrayOutputStream = new ByteArrayOutputStream + val objectOutput: ObjectOutputStream = new ObjectOutputStream(byteOutput) + objectOutput.writeObject(o) + objectOutput.close() + Base64.getEncoder.encodeToString(byteOutput.toByteArray) } /** Deserialize an arbitrary object from String. */ @@ -169,7 +168,7 @@ object MacroCompilerUtil { val ois: ObjectInputStream = new ObjectInputStream(new ByteArrayInputStream(data)) val o = ois.readObject ois.close() - return o + o } } diff --git a/src/main/scala/barstools/macros/MacroCompiler.scala b/src/main/scala/barstools/macros/MacroCompiler.scala index 5a5804b7..968e6b30 100644 --- a/src/main/scala/barstools/macros/MacroCompiler.scala +++ b/src/main/scala/barstools/macros/MacroCompiler.scala @@ -11,14 +11,17 @@ import barstools.macros.Utils._ import firrtl.Utils.{one, zero, BoolType} import firrtl.annotations._ import firrtl.ir._ +import firrtl.options.Dependency +import firrtl.stage.TransformManager.TransformDependency import firrtl.stage.{FirrtlSourceAnnotation, FirrtlStage, Forms, OutputFileAnnotation, RunFirrtlTransformAnnotation} import firrtl.transforms.NoDCEAnnotation import firrtl.{PrimOps, _} import mdf.macrolib.{PolarizedPort, PortPolarity, SRAMCompiler, SRAMGroup, SRAMMacro} import java.io.{File, FileWriter} -import scala.collection.mutable.{ArrayBuffer, HashMap} -import scala.io.Source +import scala.annotation.tailrec +import scala.collection.mutable +import scala.collection.mutable.ArrayBuffer case class MacroCompilerException(msg: String) extends Exception(msg) @@ -61,7 +64,7 @@ object MacroCompilerAnnotation { * TODO: Maybe set the default to FallbackSynflops (typical for * vlsi_mem_gen-like scripts) once it's implemented? */ - val Default = CompileAvailable + val Default: CompilerMode = CompileAvailable // Options as list of (CompilerMode, command-line name, description) val options: Seq[(CompilerMode, String, String)] = Seq( @@ -142,8 +145,8 @@ class MacroCompilerPass( // ((0,21), (22,21)) is illegal and will throw an assert private def checkBitPairs(bitPairs: Seq[(BigInt, BigInt)]): Unit = { bitPairs.foldLeft(BigInt(-1))((lastBit, nextPair) => { - assert(lastBit + 1 == nextPair._1, s"Pair's first bit ${nextPair._1} does not follow last bit ${lastBit}"); - assert(nextPair._2 >= nextPair._1, s"Pair ${nextPair} in bitPairs ${bitPairs} is illegal"); + assert(lastBit + 1 == nextPair._1, s"Pair's first bit ${nextPair._1} does not follow last bit $lastBit") + assert(nextPair._2 >= nextPair._1, s"Pair $nextPair in bitPairs $bitPairs is illegal") nextPair._2 }) } @@ -207,10 +210,10 @@ class MacroCompilerPass( // Only the lib is masked. // Not an issue; we can just make all the bits in the lib mask enabled. - case (None, Some(p)) => splitMemory(libWidth) + case (None, Some(_)) => splitMemory(libWidth) // Only the mem is masked. - case (Some(p), None) => { + case (Some(p), None) => if (p % libPort.src.width.get == 0) { // If the mem mask is a multiple of the lib width, then we're good. // Just roll over every lib width as usual. @@ -236,10 +239,9 @@ class MacroCompilerPass( return Seq() } } - } // Both lib and mem are masked. - case (Some(m), Some(l)) => { + case (Some(m), Some(l)) => if (m == l) { // Lib maskGran == mem maskGran, no problems splitMemory(libWidth) @@ -272,7 +274,6 @@ class MacroCompilerPass( return Seq() } } - } } } @@ -289,10 +290,10 @@ class MacroCompilerPass( } } // Add in the last chunk if there are any leftovers - bitPairs += ((currentLSB, mem.src.width.toInt - 1)) + bitPairs += ((currentLSB, mem.src.width - 1)) - bitPairs.toSeq - } + bitPairs + }.toSeq def compile(mem: Macro, lib: Macro): Option[(Module, Macro)] = { assert( @@ -312,9 +313,9 @@ class MacroCompilerPass( // Depth mapping val stmts = ArrayBuffer[Statement]() - val outputs = HashMap[String, ArrayBuffer[(Expression, Expression)]]() - val selects = HashMap[String, Expression]() - val selectRegs = HashMap[String, Expression]() + val outputs = mutable.HashMap[String, ArrayBuffer[(Expression, Expression)]]() + val selects = mutable.HashMap[String, Expression]() + val selectRegs = mutable.HashMap[String, Expression]() /* Palmer: If we've got a parallel memory then we've got to take the * address bits into account. */ if (mem.src.depth > lib.src.depth) { @@ -342,9 +343,9 @@ class MacroCompilerPass( } } } - for ((off, i) <- (BigInt(0).until(mem.src.depth, lib.src.depth)).zipWithIndex) { + for ((_, i) <- BigInt(0).until(mem.src.depth, lib.src.depth).zipWithIndex) { for (j <- bitPairs.indices) { - val name = s"mem_${i}_${j}" + val name = s"mem_${i}_$j" // Create the instance. stmts += WDefInstance(NoInfo, name, lib.src.name, lib.tpe) // Connect extra ports of the lib. @@ -370,7 +371,7 @@ class MacroCompilerPass( } val cats = ArrayBuffer[Expression]() for (((low, high), j) <- bitPairs.zipWithIndex) { - val inst = WRef(s"mem_${i}_${j}", lib.tpe) + val inst = WRef(s"mem_${i}_$j", lib.tpe) def connectPorts2(mem: Expression, lib: String, polarity: Option[PortPolarity]): Statement = Connect(NoInfo, WSubField(inst, lib), portToExpression(mem, polarity)) @@ -396,11 +397,11 @@ class MacroCompilerPass( * together a bunch of narrower memories, which can only be * done after generating all the memories. This saves up the * output statements for later. */ - val name = s"${mem}_${i}_${j}" // This name is the output from the instance (mem vs ${mem}). + val name = s"${mem}_${i}_$j" // This name is the output from the instance (mem vs ${mem}). val exp = portToExpression(bits(WSubField(inst, lib), high - low, 0), Some(lib_polarity)) stmts += DefNode(NoInfo, name, exp) cats += WRef(name) - case (None, Some(lib)) => + case (None, Some(_)) => /* Palmer: If the inner memory has an output port but the outer * one doesn't then it's safe to just leave the outer * port floating. */ @@ -410,7 +411,7 @@ class MacroCompilerPass( * there's nothing to do. */ case (Some(PolarizedPort(mem, _)), None) => System.err.println("WARNING: Unable to match output ports on memory") - System.err.println(s" outer output port: ${mem}") + System.err.println(s" outer output port: $mem") return None } @@ -434,7 +435,7 @@ class MacroCompilerPass( * there's nothing to do. */ case (Some(PolarizedPort(mem, _)), None) => System.err.println("WARNING: Unable to match input ports on memory") - System.err.println(s" outer input port: ${mem}") + System.err.println(s" outer input port: $mem") return None } @@ -452,7 +453,7 @@ class MacroCompilerPass( // If we have a mem maskGran less than the lib's maskGran, we'll have to take the smaller maskGran. // Example: if we have a lib whose maskGran is 8 but our mem's maskGran is 4. // The other case is if we're using a larger lib than mem. - val usingLessThanLibMaskGran = (memPort.src.maskGran.get < libPort.src.effectiveMaskGran) + val usingLessThanLibMaskGran = memPort.src.maskGran.get < libPort.src.effectiveMaskGran val effectiveLibWidth = if (usingLessThanLibMaskGran) memPort.src.maskGran.get @@ -460,24 +461,22 @@ class MacroCompilerPass( libPort.src.width.get cat( - ( - (0 until libPort.src.width.get by libPort.src.effectiveMaskGran) - .map(i => { - if (usingLessThanLibMaskGran && i >= effectiveLibWidth) { - // If the memMaskGran is smaller than the lib's gran, then - // zero out the upper bits. + (0 until libPort.src.width.get by libPort.src.effectiveMaskGran) + .map(i => { + if (usingLessThanLibMaskGran && i >= effectiveLibWidth) { + // If the memMaskGran is smaller than the lib's gran, then + // zero out the upper bits. + zero + } else { + if ((low + i) >= memPort.src.width.get) { + // If our bit is larger than the whole width of the mem, just zero out the upper bits. zero } else { - if ((low + i) >= memPort.src.width.get) { - // If our bit is larger than the whole width of the mem, just zero out the upper bits. - zero - } else { - // Pick the appropriate bit from the mem mask. - bits(WRef(mem), (low + i) / memPort.src.effectiveMaskGran) - } + // Pick the appropriate bit from the mem mask. + bits(WRef(mem), (low + i) / memPort.src.effectiveMaskGran) } - }) - ) + } + }) .reverse ) } @@ -486,7 +485,7 @@ class MacroCompilerPass( * all bits of the lib mask port. */ if (libPort.src.maskPort.isDefined) { val width = libPort.src.width.get / libPort.src.effectiveMaskGran - val value = (BigInt(1) << width.toInt) - 1 + val value = (BigInt(1) << width) - 1 UIntLiteral(value, IntWidth(width)) } else { // No mask ports on either side. @@ -551,17 +550,15 @@ class MacroCompilerPass( * memory that actually has them then we can use the * write enable port instead of the mask port. */ chipEnable match { - case Some(PolarizedPort(en, en_polarity)) => { + case Some(PolarizedPort(en, en_polarity)) => stmts += connectPorts(andAddrMatch(and(memWriteEnable, memMask)), we, we_polarity) stmts += connectPorts(andAddrMatch(memChipEnable), en, en_polarity) - } - case _ => { + case _ => stmts += connectPorts( andAddrMatch(and(and(memWriteEnable, memChipEnable), memMask)), we, we_polarity ) - } } } else { System.err.println("cannot emulate multi-bit mask ports with write enable") @@ -575,9 +572,9 @@ class MacroCompilerPass( // Cat macro outputs for selection memPort.src.output match { case Some(PolarizedPort(mem, _)) if cats.nonEmpty => - val name = s"${mem}_${i}" + val name = s"${mem}_$i" stmts += DefNode(NoInfo, name, cat(cats.toSeq.reverse)) - (outputs.getOrElseUpdate(mem, ArrayBuffer[(Expression, Expression)]())) += + outputs.getOrElseUpdate(mem, ArrayBuffer[(Expression, Expression)]()) += (addrMatchReg -> WRef(name)) case _ => } @@ -590,7 +587,7 @@ class MacroCompilerPass( case Some(PolarizedPort(mem, _)) => outputs.get(mem) match { case Some(select) => - val output = (select.foldRight(zeroOutputValue)) { case ((cond, tval), fval) => + val output = select.foldRight(zeroOutputValue) { case ((cond, tval), fval) => Mux(cond, tval, fval, fval.tpe) } stmts += Connect(NoInfo, WRef(mem), output) @@ -610,11 +607,11 @@ class MacroCompilerPass( // Try to compile each of the memories in mems. // The 'state' is c.modules, which is a list of all the firrtl modules // in the 'circuit'. - (mems.foldLeft(c.modules)) { (modules, mem) => + mems.foldLeft(c.modules) { (modules, mem) => val sram = mem.src def groupMatchesMask(group: SRAMGroup, mem: SRAMMacro): Boolean = { - val memMask = mem.ports.map(_.maskGran).find(_.isDefined).map(_.get) - val libMask = group.ports.map(_.maskGran).find(_.isDefined).map(_.get) + val memMask = mem.ports.map(_.maskGran).find(_.isDefined).flatten + val libMask = group.ports.map(_.maskGran).find(_.isDefined).flatten (memMask, libMask) match { case (None, _) => true case (Some(_), None) => false @@ -623,23 +620,22 @@ class MacroCompilerPass( } // Add compiler memories that might map well to libs val compLibs = compilers match { - case Some(SRAMCompiler(_, groups)) => { + case Some(SRAMCompiler(_, groups)) => groups .filter(g => g.family == sram.family && groupMatchesMask(g, sram)) .map(g => { for { w <- g.width - d <- g.depth if ((sram.width % w == 0) && (sram.depth % d == 0)) + d <- g.depth if (sram.width % w == 0) && (sram.depth % d == 0) } yield Seq(new Macro(buildSRAMMacro(g, d, w, g.vt.head))) }) - } case None => Seq() } val fullLibs = libs ++ compLibs.flatten.flatten // Try to compile mem against each lib in libs, keeping track of the // best compiled version, external lib used, and cost. - val (best, cost) = (fullLibs.foldLeft(None: Option[(Module, Macro)], Double.MaxValue)) { + val (best, _) = fullLibs.foldLeft(None: Option[(Module, Macro)], Double.MaxValue) { case ((best, cost), lib) if mem.src.ports.size != lib.src.ports.size => /* Palmer: FIXME: This just assumes the Chisel and vendor ports are in the same * order, but I'm starting with what actually gets generated. */ @@ -648,15 +644,14 @@ class MacroCompilerPass( case ((best, cost), lib) => // Run the cost function to evaluate this potential compile. costMetric.cost(mem, lib) match { - case Some(newCost) => { + case Some(newCost) => //System.err.println(s"Cost of ${lib.src.name} for ${mem.src.name}: ${newCost}") // Try compiling compile(mem, lib) match { // If it was successful and the new cost is lower - case Some(p) if (newCost < cost) => (Some(p), newCost) - case _ => (best, cost) + case Some(p) if newCost < cost => (Some(p), newCost) + case _ => (best, cost) } - } case _ => (best, cost) // Cost function rejected this combination. } } @@ -665,27 +660,25 @@ class MacroCompilerPass( // in the modules list with a compiled version, as well as the extmodule // stub for the lib. best match { - case None => { + case None => if (mode == MacroCompilerAnnotation.Strict) - throw new MacroCompilerException( + throw MacroCompilerException( s"Target memory ${mem.src.name} could not be compiled and strict mode is activated - aborting." ) else modules - } case Some((mod, bb)) => hammerIR match { - case Some(f) => { + case Some(f) => val hammerIRWriter = new FileWriter(new File(f), !firstLib) if (firstLib) hammerIRWriter.write("[\n") hammerIRWriter.write(bb.src.toJSON().toString()) hammerIRWriter.write("\n,\n") hammerIRWriter.close() firstLib = false - } case None => } - (modules.filterNot(m => m.name == mod.name || m.name == bb.blackbox.name)) ++ Seq(mod, bb.blackbox) + modules.filterNot(m => m.name == mod.name || m.name == bb.blackbox.name) ++ Seq(mod, bb.blackbox) } } case _ => c.modules @@ -695,12 +688,14 @@ class MacroCompilerPass( } class MacroCompilerTransform extends Transform with DependencyAPIMigration { - override def prerequisites = Forms.LowForm - override def optionalPrerequisites = Forms.LowFormOptimized - override def optionalPrerequisiteOf = Forms.LowEmitters + override def prerequisites: Seq[TransformDependency] = Forms.LowForm + override def optionalPrerequisites: Seq[TransformDependency] = Forms.LowFormOptimized + override def optionalPrerequisiteOf: Seq[Dependency[Emitter]] = Forms.LowEmitters override def invalidates(a: Transform) = false - def execute(state: CircuitState) = state.annotations.collect { case a: MacroCompilerAnnotation => a } match { + def execute(state: CircuitState): CircuitState = state.annotations.collect { case a: MacroCompilerAnnotation => + a + } match { case Seq(anno: MacroCompilerAnnotation) => val MacroCompilerAnnotation.Params( memFile, @@ -718,7 +713,7 @@ class MacroCompilerTransform extends Transform with DependencyAPIMigration { } // Check that we don't have any modules both forced to compile and synflops. - assert((forceCompile.intersect(forceSynflops)).isEmpty, "Cannot have modules both forced to compile and synflops") + assert(forceCompile.intersect(forceSynflops).isEmpty, "Cannot have modules both forced to compile and synflops") // Read, eliminate None, get only SRAM, make firrtl macro val mems: Option[Seq[Macro]] = (memFileFormat match { @@ -753,6 +748,7 @@ class MacroCompilerTransform extends Transform with DependencyAPIMigration { memsAdjustedForMode.filterNot(m => forceSynflops.contains(m.src.name)) ++ setToSeqMacro(forceCompile) } val memSynflops: Seq[Macro] = mems.map { actualMems => + // val memsAdjustedForMode = if (mode == MacroCompilerAnnotation.Synflops) actualMems else Seq.empty memsAdjustedForMode.filterNot(m => forceCompile.contains(m.src.name)) ++ setToSeqMacro(forceSynflops) }.getOrElse(Seq.empty) @@ -768,15 +764,15 @@ class MacroCompilerTransform extends Transform with DependencyAPIMigration { }) ) ) - (transforms.foldLeft(state))((s, xform) => xform.runTransform(s)) + transforms.foldLeft(state)((s, xform) => xform.runTransform(s)) case _ => state } } class MacroCompilerOptimizations extends SeqTransform with DependencyAPIMigration { - override def prerequisites = Forms.LowForm - override def optionalPrerequisites = Forms.LowFormOptimized - override def optionalPrerequisiteOf = Forms.LowEmitters + override def prerequisites: Seq[TransformDependency] = Forms.LowForm + override def optionalPrerequisites: Seq[TransformDependency] = Forms.LowFormOptimized + override def optionalPrerequisiteOf: Seq[Dependency[Emitter]] = Forms.LowEmitters override def invalidates(a: Transform) = false def transforms: Seq[Transform] = Seq( @@ -823,6 +819,7 @@ object MacroCompiler extends App { " --mode:" ) ++ modeOptions).mkString("\n") + @tailrec def parseArgs( map: MacroParamMap, costMap: CostParamMap, @@ -855,22 +852,22 @@ object MacroCompiler extends App { parseArgs(map, costMap, forcedMemories.copy(_2 = forcedMemories._2 + value), tail) case "--mode" :: value :: tail => parseArgs(map + (Mode -> value), costMap, forcedMemories, tail) - case arg :: tail => + case arg :: _ => println(s"Unknown field $arg\n") println(usage) sys.exit(1) } - def run(args: List[String]) { + def run(args: List[String]): Unit = { val (params, costParams, forcedMemories) = parseArgs(Map[MacroParam, String](), Map[String, String](), (Set.empty, Set.empty), args) try { val macros = params.get(MacrosFormat) match { case Some("conf") => - filterForSRAM(readConfFromPath(params.get(Macros))).get.map(x => (new Macro(x)).blackbox) + filterForSRAM(readConfFromPath(params.get(Macros))).get.map(x => new Macro(x).blackbox) case _ => filterForSRAM(mdf.macrolib.Utils.readMDFFromPath(params.get(Macros))).get - .map(x => (new Macro(x)).blackbox) + .map(x => new Macro(x).blackbox) } if (macros.nonEmpty) { @@ -913,14 +910,13 @@ object MacroCompiler extends App { ) params.get(HammerIR) match { - case Some(hammerIRFile: String) => { - val lines = Source.fromFile(hammerIRFile).getLines().toList + case Some(hammerIRFile: String) => + val lines = FileUtils.getLines(hammerIRFile).toList val hammerIRWriter = new FileWriter(new File(hammerIRFile)) // JSON means we need to destroy the last comma :( lines.dropRight(1).foreach(l => hammerIRWriter.write(l + "\n")) hammerIRWriter.write("]\n") hammerIRWriter.close() - } case None => } } else { @@ -929,11 +925,10 @@ object MacroCompiler extends App { // Emit empty verilog file if no macros found params.get(Verilog) match { - case Some(verilogFile: String) => { + case Some(verilogFile: String) => // Create an empty verilog file val verilogWriter = new FileWriter(new File(verilogFile)) verilogWriter.close() - } case None => } } diff --git a/src/main/scala/barstools/macros/SynFlops.scala b/src/main/scala/barstools/macros/SynFlopsPass.scala similarity index 92% rename from src/main/scala/barstools/macros/SynFlops.scala rename to src/main/scala/barstools/macros/SynFlopsPass.scala index f7245144..5dda0476 100644 --- a/src/main/scala/barstools/macros/SynFlops.scala +++ b/src/main/scala/barstools/macros/SynFlopsPass.scala @@ -8,11 +8,13 @@ import firrtl._ import firrtl.ir._ import firrtl.passes.MemPortUtils.memPortField +import scala.collection.mutable + class SynFlopsPass(synflops: Boolean, libs: Seq[Macro]) extends firrtl.passes.Pass { - val extraMods = scala.collection.mutable.ArrayBuffer.empty[Module] - lazy val libMods = (libs.map { lib => + val extraMods: mutable.ArrayBuffer[Module] = scala.collection.mutable.ArrayBuffer.empty[Module] + lazy val libMods: Map[String, Module] = libs.map { lib => lib.src.name -> { - val (dataType, dataWidth) = (lib.src.ports.foldLeft(None: Option[BigInt]))((res, port) => + val (dataType, dataWidth) = lib.src.ports.foldLeft(None: Option[BigInt])((res, port) => (res, port.maskPort) match { case (_, None) => res @@ -28,7 +30,6 @@ class SynFlopsPass(synflops: Boolean, libs: Seq[Macro]) extends firrtl.passes.Pa } val maxDepth = firrtl.Utils.min(lib.src.depth, 1 << 26) - val numMems = lib.src.depth / maxDepth // Change macro to be mapped onto to look like the below mem // by changing its depth, and width @@ -46,7 +47,7 @@ class SynFlopsPass(synflops: Boolean, libs: Seq[Macro]) extends firrtl.passes.Pa ) ) ) - val mod_macro = (new MacroCompilerPass(None, None, None, None)).compile(lib, lib_macro) + val mod_macro = new MacroCompilerPass(None, None, None, None).compile(lib, lib_macro) val (real_mod, real_macro) = mod_macro.get val mem = DefMemory( @@ -142,10 +143,10 @@ class SynFlopsPass(synflops: Boolean, libs: Seq[Macro]) extends firrtl.passes.Pa extraMods.append(real_macro.module(Block(mem +: (readConnects ++ writeConnects ++ readwriteConnects)))) real_mod } - }).toMap + }.toMap def run(c: Circuit): Circuit = { if (!synflops) c - else c.copy(modules = (c.modules.map(m => libMods.getOrElse(m.name, m))) ++ extraMods) + else c.copy(modules = c.modules.map(m => libMods.getOrElse(m.name, m)) ++ extraMods) } } diff --git a/src/main/scala/barstools/macros/Utils.scala b/src/main/scala/barstools/macros/Utils.scala index 9afa51f3..1b4fa8fe 100644 --- a/src/main/scala/barstools/macros/Utils.scala +++ b/src/main/scala/barstools/macros/Utils.scala @@ -15,28 +15,28 @@ object MacroCompilerMath { } class FirrtlMacroPort(port: MacroPort) { - val src = port + val src: MacroPort = port - val isReader = port.output.nonEmpty && port.input.isEmpty - val isWriter = port.input.nonEmpty && port.output.isEmpty - val isReadWriter = port.input.nonEmpty && port.output.nonEmpty + val isReader: Boolean = port.output.nonEmpty && port.input.isEmpty + val isWriter: Boolean = port.input.nonEmpty && port.output.isEmpty + val isReadWriter: Boolean = port.input.nonEmpty && port.output.nonEmpty - val addrType = UIntType(IntWidth(MacroCompilerMath.ceilLog2(port.depth.get).max(1))) - val dataType = UIntType(IntWidth(port.width.get)) - val maskType = UIntType(IntWidth(port.width.get / port.effectiveMaskGran)) + val addrType: UIntType = UIntType(IntWidth(MacroCompilerMath.ceilLog2(port.depth.get).max(1))) + val dataType: UIntType = UIntType(IntWidth(port.width.get)) + val maskType: UIntType = UIntType(IntWidth(port.width.get / port.effectiveMaskGran)) // Bundle representing this macro port. - val tpe = BundleType( + val tpe: BundleType = BundleType( Seq(Field(port.address.name, Flip, addrType)) ++ - (port.clock.map(p => Field(p.name, Flip, ClockType))) ++ - (port.input.map(p => Field(p.name, Flip, dataType))) ++ - (port.output.map(p => Field(p.name, Default, dataType))) ++ - (port.chipEnable.map(p => Field(p.name, Flip, BoolType))) ++ - (port.readEnable.map(p => Field(p.name, Flip, BoolType))) ++ - (port.writeEnable.map(p => Field(p.name, Flip, BoolType))) ++ - (port.maskPort.map(p => Field(p.name, Flip, maskType))) + port.clock.map(p => Field(p.name, Flip, ClockType)) ++ + port.input.map(p => Field(p.name, Flip, dataType)) ++ + port.output.map(p => Field(p.name, Default, dataType)) ++ + port.chipEnable.map(p => Field(p.name, Flip, BoolType)) ++ + port.readEnable.map(p => Field(p.name, Flip, BoolType)) ++ + port.writeEnable.map(p => Field(p.name, Flip, BoolType)) ++ + port.maskPort.map(p => Field(p.name, Flip, maskType)) ) - val ports = tpe.fields.map(f => + val ports: Seq[Port] = tpe.fields.map(f => Port( NoInfo, f.name, @@ -51,30 +51,30 @@ class FirrtlMacroPort(port: MacroPort) { // Reads an SRAMMacro and generates firrtl blackboxes. class Macro(srcMacro: SRAMMacro) { - val src = srcMacro + val src: SRAMMacro = srcMacro - val firrtlPorts = srcMacro.ports.map { new FirrtlMacroPort(_) } + val firrtlPorts: Seq[FirrtlMacroPort] = srcMacro.ports.map { new FirrtlMacroPort(_) } - val writers = firrtlPorts.filter(p => p.isWriter) - val readers = firrtlPorts.filter(p => p.isReader) - val readwriters = firrtlPorts.filter(p => p.isReadWriter) + val writers: Seq[FirrtlMacroPort] = firrtlPorts.filter(p => p.isWriter) + val readers: Seq[FirrtlMacroPort] = firrtlPorts.filter(p => p.isReader) + val readwriters: Seq[FirrtlMacroPort] = firrtlPorts.filter(p => p.isReadWriter) - val sortedPorts = writers ++ readers ++ readwriters - val extraPorts = srcMacro.extraPorts.map { p => + val sortedPorts: Seq[FirrtlMacroPort] = writers ++ readers ++ readwriters + val extraPorts: Seq[(String, UIntLiteral)] = srcMacro.extraPorts.map { p => assert(p.portType == Constant) // TODO: release it? val name = p.name val width = BigInt(p.width.toLong) val value = BigInt(p.value.toLong) - (name -> UIntLiteral(value, IntWidth(width))) + name -> UIntLiteral(value, IntWidth(width)) } // Bundle representing this memory blackbox - val tpe = BundleType(firrtlPorts.flatMap(_.tpe.fields)) + val tpe: BundleType = BundleType(firrtlPorts.flatMap(_.tpe.fields)) - private val modPorts = (firrtlPorts.flatMap(_.ports)) ++ - (extraPorts.map { case (name, value) => Port(NoInfo, name, Input, value.tpe) }) - val blackbox = ExtModule(NoInfo, srcMacro.name, modPorts, srcMacro.name, Nil) - def module(body: Statement) = Module(NoInfo, srcMacro.name, modPorts, body) + private val modPorts = firrtlPorts.flatMap(_.ports) ++ + extraPorts.map { case (name, value) => Port(NoInfo, name, Input, value.tpe) } + val blackbox: ExtModule = ExtModule(NoInfo, srcMacro.name, modPorts, srcMacro.name, Nil) + def module(body: Statement): Module = Module(NoInfo, srcMacro.name, modPorts, body) } object Utils { @@ -87,7 +87,7 @@ object Utils { } // This utility reads a conf in and returns MDF like mdf.macrolib.Utils.readMDFFromPath def readConfFromPath(path: Option[String]): Option[Seq[mdf.macrolib.Macro]] = { - path.map((p) => Utils.readConfFromString(scala.io.Source.fromFile(p).mkString)) + path.map(p => Utils.readConfFromString(FileUtils.getText(p))) } def readConfFromString(str: String): Seq[mdf.macrolib.Macro] = { MemConf.fromString(str).map { m: MemConf => @@ -102,13 +102,13 @@ object Utils { } } def portSpecToFamily(ports: Seq[MemPort]): String = { - val numR = ports.count(_ match { case ReadPort => true; case _ => false }) - val numW = ports.count(_ match { case WritePort | MaskedWritePort => true; case _ => false }) - val numRW = ports.count(_ match { case ReadWritePort | MaskedReadWritePort => true; case _ => false }) + val numR = ports.count { case ReadPort => true; case _ => false } + val numW = ports.count { case WritePort | MaskedWritePort => true; case _ => false } + val numRW = ports.count { case ReadWritePort | MaskedReadWritePort => true; case _ => false } val numRStr = if (numR > 0) s"${numR}r" else "" val numWStr = if (numW > 0) s"${numW}w" else "" val numRWStr = if (numRW > 0) s"${numRW}rw" else "" - return numRStr + numWStr + numRWStr + numRStr + numWStr + numRWStr } // This translates between two represenations of ports def portSpecToMacroPort(width: Int, depth: BigInt, maskGran: Option[Int], ports: Seq[MemPort]): Seq[MacroPort] = { @@ -116,76 +116,69 @@ object Utils { var numW = 0 var numRW = 0 ports.map { - _ match { - case ReadPort => { - val portName = s"R${numR}" - numR += 1 - MacroPort( - width = Some(width), - depth = Some(depth), - address = PolarizedPort(s"${portName}_addr", ActiveHigh), - clock = Some(PolarizedPort(s"${portName}_clk", PositiveEdge)), - readEnable = Some(PolarizedPort(s"${portName}_en", ActiveHigh)), - output = Some(PolarizedPort(s"${portName}_data", ActiveHigh)) - ) - } - case WritePort => { - val portName = s"W${numW}" - numW += 1 - MacroPort( - width = Some(width), - depth = Some(depth), - address = PolarizedPort(s"${portName}_addr", ActiveHigh), - clock = Some(PolarizedPort(s"${portName}_clk", PositiveEdge)), - writeEnable = Some(PolarizedPort(s"${portName}_en", ActiveHigh)), - input = Some(PolarizedPort(s"${portName}_data", ActiveHigh)) - ) - } - case MaskedWritePort => { - val portName = s"W${numW}" - numW += 1 - MacroPort( - width = Some(width), - depth = Some(depth), - address = PolarizedPort(s"${portName}_addr", ActiveHigh), - clock = Some(PolarizedPort(s"${portName}_clk", PositiveEdge)), - writeEnable = Some(PolarizedPort(s"${portName}_en", ActiveHigh)), - maskPort = Some(PolarizedPort(s"${portName}_mask", ActiveHigh)), - maskGran = maskGran, - input = Some(PolarizedPort(s"${portName}_data", ActiveHigh)) - ) - } - case ReadWritePort => { - val portName = s"RW${numRW}" - numRW += 1 - MacroPort( - width = Some(width), - depth = Some(depth), - address = PolarizedPort(s"${portName}_addr", ActiveHigh), - clock = Some(PolarizedPort(s"${portName}_clk", PositiveEdge)), - chipEnable = Some(PolarizedPort(s"${portName}_en", ActiveHigh)), - writeEnable = Some(PolarizedPort(s"${portName}_wmode", ActiveHigh)), - input = Some(PolarizedPort(s"${portName}_wdata", ActiveHigh)), - output = Some(PolarizedPort(s"${portName}_rdata", ActiveHigh)) - ) - } - case MaskedReadWritePort => { - val portName = s"RW${numRW}" - numRW += 1 - MacroPort( - width = Some(width), - depth = Some(depth), - address = PolarizedPort(s"${portName}_addr", ActiveHigh), - clock = Some(PolarizedPort(s"${portName}_clk", PositiveEdge)), - chipEnable = Some(PolarizedPort(s"${portName}_en", ActiveHigh)), - writeEnable = Some(PolarizedPort(s"${portName}_wmode", ActiveHigh)), - maskPort = Some(PolarizedPort(s"${portName}_wmask", ActiveHigh)), - maskGran = maskGran, - input = Some(PolarizedPort(s"${portName}_wdata", ActiveHigh)), - output = Some(PolarizedPort(s"${portName}_rdata", ActiveHigh)) - ) - } - } + case ReadPort => + val portName = s"R$numR" + numR += 1 + MacroPort( + width = Some(width), + depth = Some(depth), + address = PolarizedPort(s"${portName}_addr", ActiveHigh), + clock = Some(PolarizedPort(s"${portName}_clk", PositiveEdge)), + readEnable = Some(PolarizedPort(s"${portName}_en", ActiveHigh)), + output = Some(PolarizedPort(s"${portName}_data", ActiveHigh)) + ) + case WritePort => + val portName = s"W$numW" + numW += 1 + MacroPort( + width = Some(width), + depth = Some(depth), + address = PolarizedPort(s"${portName}_addr", ActiveHigh), + clock = Some(PolarizedPort(s"${portName}_clk", PositiveEdge)), + writeEnable = Some(PolarizedPort(s"${portName}_en", ActiveHigh)), + input = Some(PolarizedPort(s"${portName}_data", ActiveHigh)) + ) + case MaskedWritePort => + val portName = s"W$numW" + numW += 1 + MacroPort( + width = Some(width), + depth = Some(depth), + address = PolarizedPort(s"${portName}_addr", ActiveHigh), + clock = Some(PolarizedPort(s"${portName}_clk", PositiveEdge)), + writeEnable = Some(PolarizedPort(s"${portName}_en", ActiveHigh)), + maskPort = Some(PolarizedPort(s"${portName}_mask", ActiveHigh)), + maskGran = maskGran, + input = Some(PolarizedPort(s"${portName}_data", ActiveHigh)) + ) + case ReadWritePort => + val portName = s"RW$numRW" + numRW += 1 + MacroPort( + width = Some(width), + depth = Some(depth), + address = PolarizedPort(s"${portName}_addr", ActiveHigh), + clock = Some(PolarizedPort(s"${portName}_clk", PositiveEdge)), + chipEnable = Some(PolarizedPort(s"${portName}_en", ActiveHigh)), + writeEnable = Some(PolarizedPort(s"${portName}_wmode", ActiveHigh)), + input = Some(PolarizedPort(s"${portName}_wdata", ActiveHigh)), + output = Some(PolarizedPort(s"${portName}_rdata", ActiveHigh)) + ) + case MaskedReadWritePort => + val portName = s"RW$numRW" + numRW += 1 + MacroPort( + width = Some(width), + depth = Some(depth), + address = PolarizedPort(s"${portName}_addr", ActiveHigh), + clock = Some(PolarizedPort(s"${portName}_clk", PositiveEdge)), + chipEnable = Some(PolarizedPort(s"${portName}_en", ActiveHigh)), + writeEnable = Some(PolarizedPort(s"${portName}_wmode", ActiveHigh)), + maskPort = Some(PolarizedPort(s"${portName}_wmask", ActiveHigh)), + maskGran = maskGran, + input = Some(PolarizedPort(s"${portName}_wdata", ActiveHigh)), + output = Some(PolarizedPort(s"${portName}_rdata", ActiveHigh)) + ) } } def findSRAMCompiler(s: Option[Seq[mdf.macrolib.Macro]]): Option[mdf.macrolib.SRAMCompiler] = { @@ -215,7 +208,7 @@ object Utils { ) } def buildSRAMMacro(g: mdf.macrolib.SRAMGroup, d: Int, w: Int, vt: String): mdf.macrolib.SRAMMacro = { - return mdf.macrolib.SRAMMacro( + mdf.macrolib.SRAMMacro( makeName(g, d, w, vt), w, d, @@ -241,9 +234,9 @@ object Utils { } } - def and(e1: Expression, e2: Expression) = + def and(e1: Expression, e2: Expression): DoPrim = DoPrim(PrimOps.And, Seq(e1, e2), Nil, e1.tpe) - def or(e1: Expression, e2: Expression) = + def or(e1: Expression, e2: Expression): DoPrim = DoPrim(PrimOps.Or, Seq(e1, e2), Nil, e1.tpe) def bits(e: Expression, high: BigInt, low: BigInt): Expression = DoPrim(PrimOps.Bits, Seq(e), Seq(high, low), UIntType(IntWidth(high - low + 1))) @@ -251,7 +244,7 @@ object Utils { def cat(es: Seq[Expression]): Expression = if (es.size == 1) es.head else DoPrim(PrimOps.Cat, Seq(es.head, cat(es.tail)), Nil, UnknownType) - def not(e: Expression) = + def not(e: Expression): DoPrim = DoPrim(PrimOps.Not, Seq(e), Nil, e.tpe) // Convert a port to a FIRRTL expression, handling polarity along the way. diff --git a/src/test/scala/barstools/macros/CostFunction.scala b/src/test/scala/barstools/macros/CostFunction.scala index b3d5b46e..62ebfcdf 100644 --- a/src/test/scala/barstools/macros/CostFunction.scala +++ b/src/test/scala/barstools/macros/CostFunction.scala @@ -11,9 +11,9 @@ object TestMinWidthMetric extends CostMetric with CostMetricCompanion { // Smaller width = lower cost = favoured override def cost(mem: Macro, lib: Macro): Option[Double] = Some(lib.src.width) - override def commandLineParams = Map() - override def name = "TestMinWidthMetric" - override def construct(m: Map[String, String]) = TestMinWidthMetric + override def commandLineParams() = Map() + override def name() = "TestMinWidthMetric" + override def construct(m: Map[String, String]): CostMetric = TestMinWidthMetric } /** Test that cost metric selection is working. */ @@ -25,7 +25,7 @@ class SelectCostMetric extends MacroCompilerSpec with HasSRAMGenerator { // Cost metrics must be registered for them to work with the command line. CostMetric.registerCostMetric(TestMinWidthMetric) - override val costMetric = Some(TestMinWidthMetric) + override val costMetric: Option[CostMetric] = Some(TestMinWidthMetric) val libSRAMs = Seq( SRAMMacro( diff --git a/src/test/scala/barstools/macros/Functional.scala b/src/test/scala/barstools/macros/Functional.scala index 2b0dfbe0..9366f6f9 100644 --- a/src/test/scala/barstools/macros/Functional.scala +++ b/src/test/scala/barstools/macros/Functional.scala @@ -1,5 +1,6 @@ package barstools.macros +import firrtl.ir.Circuit import firrtl_interpreter.InterpretiveTester // Functional tests on memory compiler outputs. @@ -10,8 +11,8 @@ class SynchronousReadAndWrite extends MacroCompilerSpec with HasSRAMGenerator wi override lazy val memDepth = BigInt(2048) override lazy val libDepth = BigInt(1024) - compile(mem, lib, v, true) - val result = execute(mem, lib, true) + compile(mem, lib, v, synflops = true) + val result: Circuit = execute(mem, lib, synflops = true) it should "run with InterpretedTester" in { pending // Enable this when https://github.com/freechipsproject/firrtl-interpreter/pull/88 is snapshot-published @@ -70,8 +71,8 @@ class DontReadCombinationally extends MacroCompilerSpec with HasSRAMGenerator wi override lazy val memDepth = BigInt(2048) override lazy val libDepth = BigInt(1024) - compile(mem, lib, v, true) - val result = execute(mem, lib, true) + compile(mem, lib, v, synflops = true) + val result: Circuit = execute(mem, lib, synflops = true) it should "run with InterpretedTester" in { pending // Enable this when https://github.com/freechipsproject/firrtl-interpreter/pull/88 is snapshot-published diff --git a/src/test/scala/barstools/macros/MacroCompilerSpec.scala b/src/test/scala/barstools/macros/MacroCompilerSpec.scala index 2b239227..2cfcaed5 100644 --- a/src/test/scala/barstools/macros/MacroCompilerSpec.scala +++ b/src/test/scala/barstools/macros/MacroCompilerSpec.scala @@ -31,19 +31,18 @@ abstract class MacroCompilerSpec extends AnyFlatSpec with Matchers { private def costMetricCmdLine = { costMetric match { case None => Nil - case Some(m) => { - val name = m.name - val params = m.commandLineParams + case Some(m) => + val name = m.name() + val params = m.commandLineParams() List("-c", name) ++ params.flatMap { case (key, value) => List("-cp", key, value) } - } } } private def args(mem: String, lib: Option[String], v: String, synflops: Boolean, useCompiler: Boolean) = - List("-m", mem.toString, "-v", v) ++ + List("-m", mem, "-v", v) ++ (lib match { case None => Nil - case Some(l) => List("-l", l.toString) + case Some(l) => List("-l", l) }) ++ costMetricCmdLine ++ (if (synflops) List("--mode", "synflops") else Nil) ++ @@ -52,23 +51,23 @@ abstract class MacroCompilerSpec extends AnyFlatSpec with Matchers { // Run the full compiler as if from the command line interface. // Generates the Verilog; useful in testing since an error will throw an // exception. - def compile(mem: String, lib: String, v: String, synflops: Boolean) { + def compile(mem: String, lib: String, v: String, synflops: Boolean): Unit = { compile(mem, Some(lib), v, synflops) } - def compile(mem: String, lib: Option[String], v: String, synflops: Boolean, useCompiler: Boolean = false) { - var mem_full = concat(memPrefix, mem) - var lib_full = concat(libPrefix, lib) - var v_full = concat(vPrefix, v) + def compile(mem: String, lib: Option[String], v: String, synflops: Boolean, useCompiler: Boolean = false): Unit = { + val mem_full = concat(memPrefix, mem) + val lib_full = concat(libPrefix, lib) + val v_full = concat(vPrefix, v) MacroCompiler.run(args(mem_full, lib_full, v_full, synflops, useCompiler)) } // Helper functions to write macro libraries to the given files. - def writeToLib(lib: String, libs: Seq[mdf.macrolib.Macro]) = { + def writeToLib(lib: String, libs: Seq[mdf.macrolib.Macro]): Boolean = { mdf.macrolib.Utils.writeMDFToPath(Some(concat(libPrefix, lib)), libs) } - def writeToMem(mem: String, mems: Seq[mdf.macrolib.Macro]) = { + def writeToMem(mem: String, mems: Seq[mdf.macrolib.Macro]): Boolean = { mdf.macrolib.Utils.writeMDFToPath(Some(concat(memPrefix, mem)), mems) } @@ -89,16 +88,16 @@ abstract class MacroCompilerSpec extends AnyFlatSpec with Matchers { // Compare FIRRTL outputs after reparsing output with ScalaTest ("should be"). def test(result: Circuit, output: String): Unit = { val gold = RemoveEmpty.run(parse(output)) - (result.serialize) should be(gold.serialize) + result.serialize should be(gold.serialize) } // Execute the macro compiler and returns a Circuit containing the output of // the memory compiler. def execute(memFile: Option[String], libFile: Option[String], synflops: Boolean): Circuit = - execute(memFile, libFile, synflops, false) + execute(memFile, libFile, synflops, useCompiler = false) def execute(memFile: Option[String], libFile: Option[String], synflops: Boolean, useCompiler: Boolean): Circuit = { - var mem_full = concat(memPrefix, memFile) - var lib_full = concat(libPrefix, libFile) + val mem_full = concat(memPrefix, memFile) + val lib_full = concat(libPrefix, libFile) require(memFile.isDefined) val mems: Seq[Macro] = Utils.filterForSRAM(mdf.macrolib.Utils.readMDFFromPath(mem_full)).get.map(new Macro(_)) @@ -126,7 +125,7 @@ abstract class MacroCompilerSpec extends AnyFlatSpec with Matchers { new SynFlopsPass(synflops, libs.getOrElse(mems)), RemoveEmpty ) - val result: Circuit = (passes.foldLeft(circuit))((c, pass) => pass.run(c)) + val result: Circuit = passes.foldLeft(circuit)((c, pass) => pass.run(c)) result } @@ -171,7 +170,7 @@ trait HasSRAMGenerator { output = if (read) Some(PolarizedPort(name = realPrefix + "dout", polarity = ActiveHigh)) else None, input = if (write) Some(PolarizedPort(name = realPrefix + "din", polarity = ActiveHigh)) else None, maskPort = maskGran match { - case Some(x: Int) => Some(PolarizedPort(name = realPrefix + "mask", polarity = ActiveHigh)) + case Some(_: Int) => Some(PolarizedPort(name = realPrefix + "mask", polarity = ActiveHigh)) case _ => None }, maskGran = maskGran, @@ -208,16 +207,7 @@ trait HasSRAMGenerator { depth: Option[BigInt], maskGran: Option[Int] = None ): MacroPort = { - generateTestPort( - prefix, - width, - depth, - maskGran = maskGran, - write = true, - writeEnable = true, - read = true, - readEnable = false - ) + generateTestPort(prefix, width, depth, maskGran = maskGran, write = true, writeEnable = true, read = true) } // Generate a "simple" SRAM (active high/positive edge, 1 read-write port). @@ -241,12 +231,11 @@ trait HasSRAMGenerator { // Generate a "simple" SRAM group (active high/positive edge, 1 read-write port). def generateSimpleSRAMGroup( - prefix: String, - mux: Int, - depth: Range, - width: Range, - maskGran: Option[Int] = None, - extraPorts: Seq[MacroExtraPort] = List() + prefix: String, + mux: Int, + depth: Range, + width: Range, + maskGran: Option[Int] = None ): SRAMGroup = { SRAMGroup( Seq("mygroup_", "width", "x", "depth", "_", "VT"), @@ -291,7 +280,7 @@ trait HasSimpleTestGenerator { def extraTag: String = "" // "Effective" libMaskGran by considering write_enable. - val effectiveLibMaskGran = libMaskGran.getOrElse(libWidth) + val effectiveLibMaskGran: Int = libMaskGran.getOrElse(libWidth) // Override this in the sub-generator if you need a more specific name. // Defaults to using reflection to pull the name of the test using this @@ -301,23 +290,23 @@ trait HasSimpleTestGenerator { //require (memDepth >= libDepth) // Convenience variables to check if a mask exists. - val memHasMask = memMaskGran != None - val libHasMask = libMaskGran != None + val memHasMask: Boolean = memMaskGran.isDefined + val libHasMask: Boolean = libMaskGran.isDefined // We need to figure out how many mask bits there are in the mem. - val memMaskBits = if (memHasMask) memWidth / memMaskGran.get else 0 - val libMaskBits = if (libHasMask) libWidth / libMaskGran.get else 0 + val memMaskBits: Int = if (memHasMask) memWidth / memMaskGran.get else 0 + val libMaskBits: Int = if (libHasMask) libWidth / libMaskGran.get else 0 - val extraTagPrefixed = if (extraTag == "") "" else ("-" + extraTag) + val extraTagPrefixed: String = if (extraTag == "") "" else "-" + extraTag - val mem = s"mem-${generatorType}${extraTagPrefixed}.json" - val lib = s"lib-${generatorType}${extraTagPrefixed}.json" - val v = s"${generatorType}${extraTagPrefixed}.v" + val mem = s"mem-$generatorType$extraTagPrefixed.json" + val lib = s"lib-$generatorType$extraTagPrefixed.json" + val v = s"$generatorType$extraTagPrefixed.v" lazy val mem_name = "target_memory" - val mem_addr_width = MacroCompilerMath.ceilLog2(memDepth) + val mem_addr_width: Int = MacroCompilerMath.ceilLog2(memDepth) lazy val lib_name = "awesome_lib_mem" - val lib_addr_width = MacroCompilerMath.ceilLog2(libDepth) + val lib_addr_width: Int = MacroCompilerMath.ceilLog2(libDepth) // Override these to change the port prefixes if needed. def libPortPrefix: String = "lib" @@ -325,11 +314,11 @@ trait HasSimpleTestGenerator { // These generate "simple" SRAMs (1 masked read-write port) by default, // but can be overridden if need be. - def generateLibSRAM() = generateSRAM(lib_name, libPortPrefix, libWidth, libDepth, libMaskGran, extraPorts) - def generateMemSRAM() = generateSRAM(mem_name, memPortPrefix, memWidth, memDepth, memMaskGran) + def generateLibSRAM(): SRAMMacro = generateSRAM(lib_name, libPortPrefix, libWidth, libDepth, libMaskGran, extraPorts) + def generateMemSRAM(): SRAMMacro = generateSRAM(mem_name, memPortPrefix, memWidth, memDepth, memMaskGran) - def libSRAM = generateLibSRAM - def memSRAM = generateMemSRAM + def libSRAM: SRAMMacro = generateLibSRAM() + def memSRAM: SRAMMacro = generateMemSRAM() def libSRAMs: Seq[SRAMMacro] = Seq(libSRAM) def memSRAMs: Seq[SRAMMacro] = Seq(memSRAM) @@ -340,18 +329,19 @@ trait HasSimpleTestGenerator { // For masks, width it's a bit tricky since we have to consider cases like // memMaskGran = 4 and libMaskGran = 8. // Consider the actually usable libWidth in cases like the above. - val usableLibWidth = if (memMaskGran.getOrElse(Int.MaxValue) < effectiveLibMaskGran) memMaskGran.get else libWidth + val usableLibWidth: Int = + if (memMaskGran.getOrElse(Int.MaxValue) < effectiveLibMaskGran) memMaskGran.get else libWidth // Number of lib instances needed to hold the mem, in both directions. // Round up (e.g. 1.5 instances = effectively 2 instances) - val depthInstances = math.ceil(memDepth.toFloat / libDepth.toFloat).toInt - val widthInstances = math.ceil(memWidth.toFloat / usableLibWidth).toInt + val depthInstances: Int = math.ceil(memDepth.toFloat / libDepth.toFloat).toInt + val widthInstances: Int = math.ceil(memWidth.toFloat / usableLibWidth).toInt // Number of width bits in the last width-direction memory. // e.g. if memWidth = 16 and libWidth = 8, this would be 8 since the last memory 0_1 has 8 bits of input width. // e.g. if memWidth = 9 and libWidth = 8, this would be 1 since the last memory 0_1 has 1 bit of input width. - lazy val lastWidthBits = if (memWidth % usableLibWidth == 0) usableLibWidth else (memWidth % usableLibWidth) - lazy val selectBits = mem_addr_width - lib_addr_width + lazy val lastWidthBits: Int = if (memWidth % usableLibWidth == 0) usableLibWidth else memWidth % usableLibWidth + lazy val selectBits: Int = mem_addr_width - lib_addr_width /** Convenience function to generate a mask statement. * @param widthInst Width instance (mem_0_x) @@ -369,25 +359,25 @@ trait HasSimpleTestGenerator { if (memMaskGran.isEmpty) { // If there is no memory mask, we should just turn all the lib mask // bits high. - s"""mem_${depthInst}_${widthInst}.lib_mask <= UInt<${libMaskBits}>("h${((1 << libMaskBits) - 1).toHexString}")""" + s"""mem_${depthInst}_$widthInst.lib_mask <= UInt<$libMaskBits>("h${((1 << libMaskBits) - 1).toHexString}")""" } else { // Calculate which bit of outer_mask contains the given bit. // e.g. if memMaskGran = 2, libMaskGran = 1 and libWidth = 4, then // calculateMaskBit({0, 1}) = 0 and calculateMaskBit({1, 2}) = 1 def calculateMaskBit(bit: Int): Int = bit / memMaskGran.getOrElse(memWidth) - val bitsArr = ((libMaskBits - 1 to 0 by -1).map(x => { + val bitsArr = (libMaskBits - 1 to 0 by -1).map(x => { if (x * libMaskGran.get > myMemWidth) { // If we have extra mask bits leftover after the effective width, // disable those bits. """UInt<1>("h0")""" } else { val outerMaskBit = calculateMaskBit(x * libMaskGran.get + myBaseBit) - s"bits(outer_mask, ${outerMaskBit}, ${outerMaskBit})" + s"bits(outer_mask, $outerMaskBit, $outerMaskBit)" } - })) + }) val maskVal = bitsArr.reduceRight((bit, rest) => s"cat($bit, $rest)") - s"mem_${depthInst}_${widthInst}.lib_mask <= ${maskVal}" + s"mem_${depthInst}_$widthInst.lib_mask <= $maskVal" } } else "" } @@ -487,7 +477,7 @@ $extraPortsStr require(memSRAM.ports.size == 1, "Header generator only supports single RW port mem") generateReadWriteHeaderPort( memPortPrefix, - memSRAM.ports(0).readEnable.isDefined, + memSRAM.ports.head.readEnable.isDefined, if (memHasMask) Some(memMaskBits) else None ) } @@ -498,7 +488,7 @@ $extraPortsStr s""" circuit $mem_name : module $mem_name : -${generateHeaderPorts} +${generateHeaderPorts()} """ } @@ -507,7 +497,7 @@ ${generateHeaderPorts} require(libSRAM.ports.size == 1, "Footer generator only supports single RW port mem") generateReadWriteFooterPort( libPortPrefix, - libSRAM.ports(0).readEnable.isDefined, + libSRAM.ports.head.readEnable.isDefined, if (libHasMask) Some(libMaskBits) else None, extraPorts.map(p => (p.name, p.width)) ) @@ -517,7 +507,7 @@ ${generateHeaderPorts} def generateFooter(): String = { s""" extmodule $lib_name : -${generateFooterPorts} +${generateFooterPorts()} defname = $lib_name """ @@ -529,13 +519,13 @@ ${generateFooterPorts} // Generate the entire output from header, body, and footer. def generateOutput(): String = { s""" -${generateHeader} -${generateBody} -${generateFooter} +${generateHeader()} +${generateBody()} +${generateFooter()} """ } - val output = generateOutput() + val output: String = generateOutput() } // Use this trait for tests that invoke the memory compiler without lib. @@ -545,12 +535,12 @@ trait HasNoLibTestGenerator extends HasSimpleTestGenerator { // If there isn't a lib, then the "lib" will become a FIRRTL "mem", which // in turn becomes synthesized flops. // Therefore, make "lib" width/depth equal to the mem. - override lazy val libDepth = memDepth - override lazy val libWidth = memWidth - override lazy val lib_name = mem_name + override lazy val libDepth: BigInt = memDepth + override lazy val libWidth: Int = memWidth + override lazy val lib_name: String = mem_name // Do the same for port names. - override lazy val libPortPrefix = memPortPrefix + override lazy val libPortPrefix: String = memPortPrefix // If there is no lib, don't generate a body. - override def generateBody = "" + override def generateBody() = "" } diff --git a/src/test/scala/barstools/macros/Masks.scala b/src/test/scala/barstools/macros/Masks.scala index 43d6b3d6..5854eea1 100644 --- a/src/test/scala/barstools/macros/Masks.scala +++ b/src/test/scala/barstools/macros/Masks.scala @@ -23,9 +23,9 @@ class Masks_FourTypes_NonMaskedMem_NonMaskedLib with HasSimpleWidthTestGenerator { override lazy val depth = BigInt(1024) override lazy val memWidth = 32 - override lazy val memMaskGran = None + override lazy val memMaskGran: Option[Int] = None override lazy val libWidth = 8 - override lazy val libMaskGran = None + override lazy val libMaskGran: Option[Int] = None it should "compile, execute, and test" in { compileExecuteAndTest(mem, lib, v, output) @@ -38,9 +38,9 @@ class Masks_FourTypes_NonMaskedMem_MaskedLib with HasSimpleWidthTestGenerator { override lazy val depth = BigInt(1024) override lazy val memWidth = 32 - override lazy val memMaskGran = None + override lazy val memMaskGran: Option[Int] = None override lazy val libWidth = 8 - override lazy val libMaskGran = Some(2) + override lazy val libMaskGran: Option[Int] = Some(2) it should "compile, execute, and test" in { compileExecuteAndTest(mem, lib, v, output) @@ -53,9 +53,9 @@ class Masks_FourTypes_MaskedMem_NonMaskedLib with HasSimpleWidthTestGenerator { override lazy val depth = BigInt(1024) override lazy val memWidth = 32 - override lazy val memMaskGran = Some(8) + override lazy val memMaskGran: Option[Int] = Some(8) override lazy val libWidth = 8 - override lazy val libMaskGran = None + override lazy val libMaskGran: Option[Int] = None it should "compile, execute, and test" in { compileExecuteAndTest(mem, lib, v, output) @@ -68,9 +68,9 @@ class Masks_FourTypes_MaskedMem_NonMaskedLib_SmallerMaskGran with HasSimpleWidthTestGenerator { override lazy val depth = BigInt(1024) override lazy val memWidth = 32 - override lazy val memMaskGran = Some(4) + override lazy val memMaskGran: Option[Int] = Some(4) override lazy val libWidth = 8 - override lazy val libMaskGran = None + override lazy val libMaskGran: Option[Int] = None it should "compile, execute, and test" in { compileExecuteAndTest(mem, lib, v, output) @@ -83,9 +83,9 @@ class Masks_FourTypes_MaskedMem_MaskedLib with HasSimpleWidthTestGenerator { override lazy val depth = BigInt(1024) override lazy val memWidth = 32 - override lazy val memMaskGran = Some(8) + override lazy val memMaskGran: Option[Int] = Some(8) override lazy val libWidth = 16 - override lazy val libMaskGran = Some(4) + override lazy val libMaskGran: Option[Int] = Some(4) it should "compile, execute, and test" in { compileExecuteAndTest(mem, lib, v, output) @@ -98,9 +98,9 @@ class Masks_FourTypes_MaskedMem_MaskedLib_SameMaskGran with HasSimpleWidthTestGenerator { override lazy val depth = BigInt(1024) override lazy val memWidth = 32 - override lazy val memMaskGran = Some(8) + override lazy val memMaskGran: Option[Int] = Some(8) override lazy val libWidth = 16 - override lazy val libMaskGran = Some(8) + override lazy val libMaskGran: Option[Int] = Some(8) it should "compile, execute, and test" in { compileExecuteAndTest(mem, lib, v, output) @@ -113,9 +113,9 @@ class Masks_FourTypes_MaskedMem_MaskedLib_SmallerMaskGran with HasSimpleWidthTestGenerator { override lazy val depth = BigInt(1024) override lazy val memWidth = 64 - override lazy val memMaskGran = Some(4) + override lazy val memMaskGran: Option[Int] = Some(4) override lazy val libWidth = 32 - override lazy val libMaskGran = Some(8) + override lazy val libMaskGran: Option[Int] = Some(8) it should "compile, execute, and test" in { compileExecuteAndTest(mem, lib, v, output) @@ -127,9 +127,9 @@ class Masks_FourTypes_MaskedMem_MaskedLib_SmallerMaskGran class Masks_BitMaskedMem_NonMaskedLib extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator { override lazy val depth = BigInt(1024) override lazy val memWidth = 16 - override lazy val memMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(1) override lazy val libWidth = 8 - override lazy val libMaskGran = None + override lazy val libMaskGran: Option[Int] = None it should "compile, execute, and test" in { compileExecuteAndTest(mem, lib, v, output) @@ -144,8 +144,8 @@ class Masks_FPGAStyle_32_8 with HasSimpleDepthTestGenerator with MasksTestSettings { override lazy val width = 32 - override lazy val memMaskGran = Some(32) - override lazy val libMaskGran = Some(8) + override lazy val memMaskGran: Option[Int] = Some(32) + override lazy val libMaskGran: Option[Int] = Some(8) it should "compile, execute, and test" in { compileExecuteAndTest(mem, lib, v, output) @@ -160,8 +160,8 @@ class Masks_PowersOfTwo_8_1 with HasSimpleDepthTestGenerator with MasksTestSettings { override lazy val width = 64 - override lazy val memMaskGran = Some(8) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(8) + override lazy val libMaskGran: Option[Int] = Some(1) it should "compile, execute, and test" in { compileExecuteAndTest(mem, lib, v, output) @@ -174,8 +174,8 @@ class Masks_PowersOfTwo_16_1 with HasSimpleDepthTestGenerator with MasksTestSettings { override lazy val width = 64 - override lazy val memMaskGran = Some(16) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(16) + override lazy val libMaskGran: Option[Int] = Some(1) it should "compile, execute, and test" in { compileExecuteAndTest(mem, lib, v, output) @@ -188,8 +188,8 @@ class Masks_PowersOfTwo_32_1 with HasSimpleDepthTestGenerator with MasksTestSettings { override lazy val width = 64 - override lazy val memMaskGran = Some(32) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(32) + override lazy val libMaskGran: Option[Int] = Some(1) it should "compile, execute, and test" in { compileExecuteAndTest(mem, lib, v, output) @@ -202,8 +202,8 @@ class Masks_PowersOfTwo_64_1 with HasSimpleDepthTestGenerator with MasksTestSettings { override lazy val width = 64 - override lazy val memMaskGran = Some(64) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(64) + override lazy val libMaskGran: Option[Int] = Some(1) it should "compile, execute, and test" in { compileExecuteAndTest(mem, lib, v, output) @@ -218,8 +218,8 @@ class Masks_PowersOfTwo_32_4 with HasSimpleDepthTestGenerator with MasksTestSettings { override lazy val width = 128 - override lazy val memMaskGran = Some(32) - override lazy val libMaskGran = Some(4) + override lazy val memMaskGran: Option[Int] = Some(32) + override lazy val libMaskGran: Option[Int] = Some(4) it should "compile, execute, and test" in { compileExecuteAndTest(mem, lib, v, output) @@ -232,8 +232,8 @@ class Masks_PowersOfTwo_32_8 with HasSimpleDepthTestGenerator with MasksTestSettings { override lazy val width = 128 - override lazy val memMaskGran = Some(32) - override lazy val libMaskGran = Some(8) + override lazy val memMaskGran: Option[Int] = Some(32) + override lazy val libMaskGran: Option[Int] = Some(8) it should "compile, execute, and test" in { compileExecuteAndTest(mem, lib, v, output) @@ -246,8 +246,8 @@ class Masks_PowersOfTwo_8_8 with HasSimpleDepthTestGenerator with MasksTestSettings { override lazy val width = 128 - override lazy val memMaskGran = Some(8) - override lazy val libMaskGran = Some(8) + override lazy val memMaskGran: Option[Int] = Some(8) + override lazy val libMaskGran: Option[Int] = Some(8) it should "compile, execute, and test" in { compileExecuteAndTest(mem, lib, v, output) @@ -262,8 +262,8 @@ class Masks_IntegerMaskMultiple_20_10 with HasSimpleDepthTestGenerator with MasksTestSettings { override lazy val width = 20 - override lazy val memMaskGran = Some(10) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(10) + override lazy val libMaskGran: Option[Int] = Some(1) it should "compile, execute, and test" in { compileExecuteAndTest(mem, lib, v, output) @@ -276,8 +276,8 @@ class Masks_IntegerMaskMultiple_21_7 with HasSimpleDepthTestGenerator with MasksTestSettings { override lazy val width = 21 - override lazy val memMaskGran = Some(21) - override lazy val libMaskGran = Some(7) + override lazy val memMaskGran: Option[Int] = Some(21) + override lazy val libMaskGran: Option[Int] = Some(7) (it should "be enabled when non-power of two masks are supported").is(pending) //~ compileExecuteAndTest(mem, lib, v, output) @@ -289,8 +289,8 @@ class Masks_IntegerMaskMultiple_21_21 with HasSimpleDepthTestGenerator with MasksTestSettings { override lazy val width = 21 - override lazy val memMaskGran = Some(21) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(21) + override lazy val libMaskGran: Option[Int] = Some(1) it should "compile, execute, and test" in { compileExecuteAndTest(mem, lib, v, output) @@ -303,8 +303,8 @@ class Masks_IntegerMaskMultiple_84_21 with HasSimpleDepthTestGenerator with MasksTestSettings { override lazy val width = 84 - override lazy val memMaskGran = Some(21) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(21) + override lazy val libMaskGran: Option[Int] = Some(1) it should "compile, execute, and test" in { compileExecuteAndTest(mem, lib, v, output) @@ -317,8 +317,8 @@ class Masks_IntegerMaskMultiple_92_23 with HasSimpleDepthTestGenerator with MasksTestSettings { override lazy val width = 92 - override lazy val memMaskGran = Some(23) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(23) + override lazy val libMaskGran: Option[Int] = Some(1) it should "compile, execute, and test" in { compileExecuteAndTest(mem, lib, v, output) @@ -331,8 +331,8 @@ class Masks_IntegerMaskMultiple_117_13 with HasSimpleDepthTestGenerator with MasksTestSettings { override lazy val width = 117 - override lazy val memMaskGran = Some(13) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(13) + override lazy val libMaskGran: Option[Int] = Some(1) it should "compile, execute, and test" in { compileExecuteAndTest(mem, lib, v, output) @@ -345,8 +345,8 @@ class Masks_IntegerMaskMultiple_160_20 with HasSimpleDepthTestGenerator with MasksTestSettings { override lazy val width = 160 - override lazy val memMaskGran = Some(20) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(20) + override lazy val libMaskGran: Option[Int] = Some(1) it should "compile, execute, and test" in { compileExecuteAndTest(mem, lib, v, output) @@ -359,8 +359,8 @@ class Masks_IntegerMaskMultiple_184_23 with HasSimpleDepthTestGenerator with MasksTestSettings { override lazy val width = 184 - override lazy val memMaskGran = Some(23) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(23) + override lazy val libMaskGran: Option[Int] = Some(1) it should "compile, execute, and test" in { compileExecuteAndTest(mem, lib, v, output) @@ -375,8 +375,8 @@ class Masks_NonIntegerMaskMultiple_32_3 with HasSimpleDepthTestGenerator with MasksTestSettings { override lazy val width = 32 - override lazy val memMaskGran = Some(3) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(3) + override lazy val libMaskGran: Option[Int] = Some(1) (it should "be enabled when non-power of two masks are supported").is(pending) //~ compileExecuteAndTest(mem, lib, v, output) diff --git a/src/test/scala/barstools/macros/MultiPort.scala b/src/test/scala/barstools/macros/MultiPort.scala index 75eb20d7..07903e0a 100644 --- a/src/test/scala/barstools/macros/MultiPort.scala +++ b/src/test/scala/barstools/macros/MultiPort.scala @@ -8,10 +8,10 @@ class SplitWidth_2rw extends MacroCompilerSpec with HasSRAMGenerator with HasSim override lazy val depth = BigInt(1024) override lazy val memWidth = 64 - override lazy val memMaskGran = Some(16) + override lazy val memMaskGran: Option[Int] = Some(16) override lazy val libWidth = 16 - override def generateMemSRAM() = { + override def generateMemSRAM(): SRAMMacro = { SRAMMacro( name = mem_name, width = memWidth, @@ -42,7 +42,7 @@ class SplitWidth_2rw extends MacroCompilerSpec with HasSRAMGenerator with HasSim ) } - override def generateLibSRAM() = { + override def generateLibSRAM(): SRAMMacro = { SRAMMacro( name = lib_name, width = libWidth, @@ -71,16 +71,20 @@ class SplitWidth_2rw extends MacroCompilerSpec with HasSRAMGenerator with HasSim ) } - override def generateHeaderPorts() = { - generateReadWriteHeaderPort("portA", true, Some(memMaskBits)) + "\n" + generateReadWriteHeaderPort( + override def generateHeaderPorts(): String = { + generateReadWriteHeaderPort("portA", readEnable = true, Some(memMaskBits)) + "\n" + generateReadWriteHeaderPort( "portB", - true, + readEnable = true, Some(memMaskBits) ) } - override def generateFooterPorts() = { - generateReadWriteFooterPort("portA", true, None) + "\n" + generateReadWriteFooterPort("portB", true, None) + override def generateFooterPorts(): String = { + generateReadWriteFooterPort("portA", readEnable = true, None) + "\n" + generateReadWriteFooterPort( + "portB", + readEnable = true, + None + ) } override def generateBody() = @@ -151,10 +155,10 @@ class SplitWidth_1r_1w extends MacroCompilerSpec with HasSRAMGenerator with HasS override lazy val depth = BigInt(1024) override lazy val memWidth = 64 - override lazy val memMaskGran = Some(16) + override lazy val memMaskGran: Option[Int] = Some(16) override lazy val libWidth = 16 - override def generateMemSRAM() = { + override def generateMemSRAM(): SRAMMacro = { SRAMMacro( name = mem_name, width = memWidth, @@ -167,7 +171,6 @@ class SplitWidth_1r_1w extends MacroCompilerSpec with HasSRAMGenerator with HasS Some(memDepth), maskGran = memMaskGran, write = false, - writeEnable = false, read = true, readEnable = true ), @@ -178,14 +181,13 @@ class SplitWidth_1r_1w extends MacroCompilerSpec with HasSRAMGenerator with HasS maskGran = memMaskGran, write = true, writeEnable = true, - read = false, - readEnable = false + read = false ) ) ) } - override def generateLibSRAM() = { + override def generateLibSRAM(): SRAMMacro = { SRAMMacro( name = lib_name, width = libWidth, @@ -197,24 +199,15 @@ class SplitWidth_1r_1w extends MacroCompilerSpec with HasSRAMGenerator with HasS libWidth, libDepth, write = false, - writeEnable = false, read = true, readEnable = true ), - generateTestPort( - "portB", - libWidth, - libDepth, - write = true, - writeEnable = true, - read = false, - readEnable = false - ) + generateTestPort("portB", libWidth, libDepth, write = true, writeEnable = true, read = false) ) ) } - override def generateHeaderPorts() = { + override def generateHeaderPorts(): String = { generatePort( "portA", mem_addr_width, @@ -237,7 +230,7 @@ class SplitWidth_1r_1w extends MacroCompilerSpec with HasSRAMGenerator with HasS ) } - override def generateFooterPorts() = { + override def generateFooterPorts(): String = { generatePort( "portA", lib_addr_width, @@ -310,12 +303,12 @@ class SplitWidth_2rw_differentMasks extends MacroCompilerSpec with HasSRAMGenera override lazy val depth = BigInt(1024) override lazy val memWidth = 64 - override lazy val memMaskGran = Some(16) + override lazy val memMaskGran: Option[Int] = Some(16) override lazy val libWidth = 16 lazy val memMaskGranB = 8 // these generators are run at constructor time - override def generateMemSRAM() = { + override def generateMemSRAM(): SRAMMacro = { SRAMMacro( name = mem_name, width = memWidth, @@ -346,7 +339,7 @@ class SplitWidth_2rw_differentMasks extends MacroCompilerSpec with HasSRAMGenera ) } - override def generateLibSRAM() = { + override def generateLibSRAM(): SRAMMacro = { SRAMMacro( name = lib_name, width = libWidth, @@ -375,16 +368,20 @@ class SplitWidth_2rw_differentMasks extends MacroCompilerSpec with HasSRAMGenera ) } - override def generateHeaderPorts() = { - generateReadWriteHeaderPort("portA", true, Some(memMaskBits)) + "\n" + generateReadWriteHeaderPort( + override def generateHeaderPorts(): String = { + generateReadWriteHeaderPort("portA", readEnable = true, Some(memMaskBits)) + "\n" + generateReadWriteHeaderPort( "portB", - true, + readEnable = true, Some(memWidth / memMaskGranB) ) } - override def generateFooterPorts() = { - generateReadWriteFooterPort("portA", true, None) + "\n" + generateReadWriteFooterPort("portB", true, None) + override def generateFooterPorts(): String = { + generateReadWriteFooterPort("portA", readEnable = true, None) + "\n" + generateReadWriteFooterPort( + "portB", + readEnable = true, + None + ) } override def generateBody() = diff --git a/src/test/scala/barstools/macros/SRAMCompiler.scala b/src/test/scala/barstools/macros/SRAMCompiler.scala index 17f49601..750283ce 100644 --- a/src/test/scala/barstools/macros/SRAMCompiler.scala +++ b/src/test/scala/barstools/macros/SRAMCompiler.scala @@ -1,7 +1,9 @@ package barstools.macros +import mdf.macrolib + class SRAMCompiler extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator { - val compiler = generateSRAMCompiler("awesome", "A") + val compiler: macrolib.SRAMCompiler = generateSRAMCompiler("awesome", "A") val verilog = s"v-SRAMCompiler.v" override lazy val depth = BigInt(16) override lazy val memWidth = 8 @@ -15,5 +17,5 @@ class SRAMCompiler extends MacroCompilerSpec with HasSRAMGenerator with HasSimpl writeToMem(mem, Seq(generateSRAM("mymem", "X", 8, 16))) - compileExecuteAndTest(mem, Some(lib), verilog, output = output, false, true) + compileExecuteAndTest(mem, Some(lib), verilog, output = output, useCompiler = true) } diff --git a/src/test/scala/barstools/macros/SimpleSplitDepth.scala b/src/test/scala/barstools/macros/SimpleSplitDepth.scala index 5a7fc77d..7e02bc1f 100644 --- a/src/test/scala/barstools/macros/SimpleSplitDepth.scala +++ b/src/test/scala/barstools/macros/SimpleSplitDepth.scala @@ -8,8 +8,8 @@ trait HasSimpleDepthTestGenerator extends HasSimpleTestGenerator { this: MacroCompilerSpec with HasSRAMGenerator => def width: Int - override lazy val memWidth = width - override lazy val libWidth = width + override lazy val memWidth: Int = width + override lazy val libWidth: Int = width // Generate a depth-splitting body. override def generateBody(): String = { @@ -19,37 +19,38 @@ trait HasSimpleDepthTestGenerator extends HasSimpleTestGenerator { output.append( s""" node ${memPortPrefix}_addr_sel = bits(${memPortPrefix}_addr, ${mem_addr_width - 1}, $lib_addr_width) - reg ${memPortPrefix}_addr_sel_reg : UInt<${selectBits}>, ${memPortPrefix}_clk with : + reg ${memPortPrefix}_addr_sel_reg : UInt<$selectBits>, ${memPortPrefix}_clk with : reset => (UInt<1>("h0"), ${memPortPrefix}_addr_sel_reg) ${memPortPrefix}_addr_sel_reg <= mux(UInt<1>("h1"), ${memPortPrefix}_addr_sel, ${memPortPrefix}_addr_sel_reg) """ ) } - for (i <- 0 to depthInstances - 1) { + for (i <- 0 until depthInstances) { + val maskStatement = generateMaskStatement(0, i) val enableIdentifier = - if (selectBits > 0) s"""eq(${memPortPrefix}_addr_sel, UInt<${selectBits}>("h${i.toHexString}"))""" + if (selectBits > 0) s"""eq(${memPortPrefix}_addr_sel, UInt<$selectBits>("h${i.toHexString}"))""" else "UInt<1>(\"h1\")" val chipEnable = s"""UInt<1>("h1")""" val writeEnable = - if (memMaskGran.isEmpty) s"and(${memPortPrefix}_write_en, ${chipEnable})" else s"${memPortPrefix}_write_en" + if (memMaskGran.isEmpty) s"and(${memPortPrefix}_write_en, $chipEnable)" else s"${memPortPrefix}_write_en" output.append( s""" - inst mem_${i}_0 of ${lib_name} + inst mem_${i}_0 of $lib_name mem_${i}_0.${libPortPrefix}_clk <= ${memPortPrefix}_clk mem_${i}_0.${libPortPrefix}_addr <= ${memPortPrefix}_addr node ${memPortPrefix}_dout_${i}_0 = bits(mem_${i}_0.${libPortPrefix}_dout, ${width - 1}, 0) mem_${i}_0.${libPortPrefix}_din <= bits(${memPortPrefix}_din, ${width - 1}, 0) - ${maskStatement} - mem_${i}_0.${libPortPrefix}_write_en <= and(and(${writeEnable}, UInt<1>("h1")), ${enableIdentifier}) - node ${memPortPrefix}_dout_${i} = ${memPortPrefix}_dout_${i}_0 + $maskStatement + mem_${i}_0.${libPortPrefix}_write_en <= and(and($writeEnable, UInt<1>("h1")), $enableIdentifier) + node ${memPortPrefix}_dout_$i = ${memPortPrefix}_dout_${i}_0 """ ) } def generate_outer_dout_tree(i: Int, depthInstances: Int): String = { if (i > depthInstances - 1) { - s"""UInt<${libWidth}>("h0")""" + s"""UInt<$libWidth>("h0")""" } else { s"""mux(eq(${memPortPrefix}_addr_sel_reg, UInt<%d>("h%s")), ${memPortPrefix}_dout_%d, %s)""".format( selectBits, @@ -63,7 +64,7 @@ trait HasSimpleDepthTestGenerator extends HasSimpleTestGenerator { if (selectBits > 0) { output.append(generate_outer_dout_tree(0, depthInstances)) } else { - output.append(s"""mux(UInt<1>("h1"), ${memPortPrefix}_dout_0, UInt<${libWidth}>("h0"))""") + output.append(s"""mux(UInt<1>("h1"), ${memPortPrefix}_dout_0, UInt<$libWidth>("h0"))""") } output.toString @@ -143,8 +144,8 @@ class SplitDepth2048x32_mrw_lib32 extends MacroCompilerSpec with HasSRAMGenerato override lazy val width = 32 override lazy val memDepth = BigInt(2048) override lazy val libDepth = BigInt(1024) - override lazy val memMaskGran = Some(32) - override lazy val libMaskGran = Some(32) + override lazy val memMaskGran: Option[Int] = Some(32) + override lazy val libMaskGran: Option[Int] = Some(32) compileExecuteAndTest(mem, lib, v, output) } @@ -153,8 +154,8 @@ class SplitDepth2048x8_mrw_lib8 extends MacroCompilerSpec with HasSRAMGenerator override lazy val width = 8 override lazy val memDepth = BigInt(2048) override lazy val libDepth = BigInt(1024) - override lazy val memMaskGran = Some(8) - override lazy val libMaskGran = Some(8) + override lazy val memMaskGran: Option[Int] = Some(8) + override lazy val libMaskGran: Option[Int] = Some(8) compileExecuteAndTest(mem, lib, v, output) } @@ -167,8 +168,8 @@ class SplitDepth2048x64_mrw_mem32_lib8 override lazy val width = 64 override lazy val memDepth = BigInt(2048) override lazy val libDepth = BigInt(1024) - override lazy val memMaskGran = Some(32) - override lazy val libMaskGran = Some(8) + override lazy val memMaskGran: Option[Int] = Some(32) + override lazy val libMaskGran: Option[Int] = Some(8) compileExecuteAndTest(mem, lib, v, output) } @@ -181,8 +182,8 @@ class SplitDepth2048x32_mrw_mem16_lib1 override lazy val width = 32 override lazy val memDepth = BigInt(2048) override lazy val libDepth = BigInt(1024) - override lazy val memMaskGran = Some(16) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(16) + override lazy val libMaskGran: Option[Int] = Some(1) compileExecuteAndTest(mem, lib, v, output) } @@ -191,8 +192,8 @@ class SplitDepth2048x32_mrw_mem8_lib1 extends MacroCompilerSpec with HasSRAMGene override lazy val width = 32 override lazy val memDepth = BigInt(2048) override lazy val libDepth = BigInt(1024) - override lazy val memMaskGran = Some(8) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(8) + override lazy val libMaskGran: Option[Int] = Some(1) compileExecuteAndTest(mem, lib, v, output) } @@ -201,8 +202,8 @@ class SplitDepth2048x32_mrw_mem4_lib1 extends MacroCompilerSpec with HasSRAMGene override lazy val width = 32 override lazy val memDepth = BigInt(2048) override lazy val libDepth = BigInt(1024) - override lazy val memMaskGran = Some(4) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(4) + override lazy val libMaskGran: Option[Int] = Some(1) compileExecuteAndTest(mem, lib, v, output) } @@ -211,8 +212,8 @@ class SplitDepth2048x32_mrw_mem2_lib1 extends MacroCompilerSpec with HasSRAMGene override lazy val width = 32 override lazy val memDepth = BigInt(2048) override lazy val libDepth = BigInt(1024) - override lazy val memMaskGran = Some(2) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(2) + override lazy val libMaskGran: Option[Int] = Some(1) compileExecuteAndTest(mem, lib, v, output) } @@ -222,8 +223,8 @@ class SplitDepth2048x32_mrw_mem3_lib1 extends MacroCompilerSpec with HasSRAMGene override lazy val width = 32 override lazy val memDepth = BigInt(2048) override lazy val libDepth = BigInt(1024) - override lazy val memMaskGran = Some(3) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(3) + override lazy val libMaskGran: Option[Int] = Some(1) (it should "be enabled when non-power of two masks are supported").is(pending) //compileExecuteAndTest(mem, lib, v, output) @@ -233,8 +234,8 @@ class SplitDepth2048x32_mrw_mem7_lib1 extends MacroCompilerSpec with HasSRAMGene override lazy val width = 32 override lazy val memDepth = BigInt(2048) override lazy val libDepth = BigInt(1024) - override lazy val memMaskGran = Some(7) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(7) + override lazy val libMaskGran: Option[Int] = Some(1) (it should "be enabled when non-power of two masks are supported").is(pending) //compileExecuteAndTest(mem, lib, v, output) @@ -244,8 +245,8 @@ class SplitDepth2048x32_mrw_mem9_lib1 extends MacroCompilerSpec with HasSRAMGene override lazy val width = 32 override lazy val memDepth = BigInt(2048) override lazy val libDepth = BigInt(1024) - override lazy val memMaskGran = Some(9) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(9) + override lazy val libMaskGran: Option[Int] = Some(1) (it should "be enabled when non-power of two masks are supported").is(pending) //compileExecuteAndTest(mem, lib, v, output) @@ -318,8 +319,8 @@ class SplitDepth_SplitPortsNonMasked extends MacroCompilerSpec with HasSRAMGener lazy val memDepth = BigInt(2048) lazy val libDepth = BigInt(1024) - override val memPrefix = testDir - override val libPrefix = testDir + override val memPrefix: String = testDir + override val libPrefix: String = testDir import mdf.macrolib._ @@ -476,11 +477,11 @@ class SplitDepth_SplitPortsMasked extends MacroCompilerSpec with HasSRAMGenerato lazy val width = 8 lazy val memDepth = BigInt(2048) lazy val libDepth = BigInt(1024) - lazy val memMaskGran = Some(8) - lazy val libMaskGran = Some(1) + lazy val memMaskGran: Option[Int] = Some(8) + lazy val libMaskGran: Option[Int] = Some(1) - override val memPrefix = testDir - override val libPrefix = testDir + override val memPrefix: String = testDir + override val libPrefix: String = testDir import mdf.macrolib._ diff --git a/src/test/scala/barstools/macros/SimpleSplitWidth.scala b/src/test/scala/barstools/macros/SimpleSplitWidth.scala index 3cd0a6df..3dffc66f 100644 --- a/src/test/scala/barstools/macros/SimpleSplitWidth.scala +++ b/src/test/scala/barstools/macros/SimpleSplitWidth.scala @@ -7,23 +7,23 @@ trait HasSimpleWidthTestGenerator extends HasSimpleTestGenerator { this: MacroCompilerSpec with HasSRAMGenerator => def depth: BigInt - override lazy val memDepth = depth - override lazy val libDepth = depth + override lazy val memDepth: BigInt = depth + override lazy val libDepth: BigInt = depth override def generateBody(): String = { val output = new StringBuilder // Generate mem_0_ lines for number of width instances. output.append( - ((0 to widthInstances - 1).map { i: Int => + (0 until widthInstances).map { i: Int => s""" - inst mem_0_${i} of ${lib_name} + inst mem_0_$i of $lib_name """ - }).reduceLeft(_ + _) + }.reduceLeft(_ + _) ) // Generate submemory connection blocks. - output.append((for (i <- 0 to widthInstances - 1) yield { + output.append((for (i <- 0 until widthInstances) yield { // Width of this submemory. val myMemWidth = if (i == widthInstances - 1) lastWidthBits else usableLibWidth // Base bit of this submemory. @@ -37,34 +37,34 @@ trait HasSimpleWidthTestGenerator extends HasSimpleTestGenerator { // lib does not. val writeEnableBit = if (libMaskGran.isEmpty && memMaskGran.isDefined) { val outerMaskBit = myBaseBit / memMaskGran.get - s"bits(outer_mask, ${outerMaskBit}, ${outerMaskBit})" + s"bits(outer_mask, $outerMaskBit, $outerMaskBit)" } else """UInt<1>("h1")""" val chipEnable = s"""UInt<1>("h1")""" val writeEnableExpr = - if (libMaskGran.isEmpty) s"and(${memPortPrefix}_write_en, ${chipEnable})" else s"${memPortPrefix}_write_en" + if (libMaskGran.isEmpty) s"and(${memPortPrefix}_write_en, $chipEnable)" else s"${memPortPrefix}_write_en" s""" - mem_0_${i}.${libPortPrefix}_clk <= ${memPortPrefix}_clk - mem_0_${i}.${libPortPrefix}_addr <= ${memPortPrefix}_addr - node ${memPortPrefix}_dout_0_${i} = bits(mem_0_${i}.${libPortPrefix}_dout, ${myMemWidth - 1}, 0) - mem_0_${i}.${libPortPrefix}_din <= bits(${memPortPrefix}_din, ${myBaseBit + myMemWidth - 1}, ${myBaseBit}) - ${maskStatement} - mem_0_${i}.${libPortPrefix}_write_en <= and(and(${writeEnableExpr}, ${writeEnableBit}), UInt<1>("h1")) + mem_0_$i.${libPortPrefix}_clk <= ${memPortPrefix}_clk + mem_0_$i.${libPortPrefix}_addr <= ${memPortPrefix}_addr + node ${memPortPrefix}_dout_0_$i = bits(mem_0_$i.${libPortPrefix}_dout, ${myMemWidth - 1}, 0) + mem_0_$i.${libPortPrefix}_din <= bits(${memPortPrefix}_din, ${myBaseBit + myMemWidth - 1}, $myBaseBit) + $maskStatement + mem_0_$i.${libPortPrefix}_write_en <= and(and($writeEnableExpr, $writeEnableBit), UInt<1>("h1")) """ }).reduceLeft(_ + _)) // Generate final output that concats together the sub-memories. // e.g. cat(outer_dout_0_2, cat(outer_dout_0_1, outer_dout_0_0)) output.append { - val doutStatements = ((widthInstances - 1 to 0 by -1).map(i => s"${memPortPrefix}_dout_0_${i}")) + val doutStatements = (widthInstances - 1 to 0 by -1).map(i => s"${memPortPrefix}_dout_0_$i") val catStmt = doutStatements.init.foldRight(doutStatements.last)((l: String, r: String) => s"cat($l, $r)") s""" - node ${memPortPrefix}_dout_0 = ${catStmt} + node ${memPortPrefix}_dout_0 = $catStmt """ } output.append(s""" - ${memPortPrefix}_dout <= mux(UInt<1>("h1"), ${memPortPrefix}_dout_0, UInt<${memWidth}>("h0")) + ${memPortPrefix}_dout <= mux(UInt<1>("h1"), ${memPortPrefix}_dout_0, UInt<$memWidth>("h0")) """) output.toString } @@ -276,8 +276,8 @@ class SplitWidth1024x8_memGran_8_libGran_1_rw override lazy val depth = BigInt(1024) override lazy val memWidth = 8 override lazy val libWidth = 8 - override lazy val memMaskGran = Some(8) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(8) + override lazy val libMaskGran: Option[Int] = Some(1) compileExecuteAndTest(mem, lib, v, output) } @@ -289,8 +289,8 @@ class SplitWidth1024x16_memGran_8_libGran_1_rw override lazy val depth = BigInt(1024) override lazy val memWidth = 16 override lazy val libWidth = 8 - override lazy val memMaskGran = Some(8) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(8) + override lazy val libMaskGran: Option[Int] = Some(1) compileExecuteAndTest(mem, lib, v, output) } @@ -302,8 +302,8 @@ class SplitWidth1024x16_memGran_8_libGran_8_rw override lazy val depth = BigInt(1024) override lazy val memWidth = 16 override lazy val libWidth = 8 - override lazy val memMaskGran = Some(8) - override lazy val libMaskGran = Some(8) + override lazy val memMaskGran: Option[Int] = Some(8) + override lazy val libMaskGran: Option[Int] = Some(8) compileExecuteAndTest(mem, lib, v, output) } @@ -315,8 +315,8 @@ class SplitWidth1024x128_memGran_8_libGran_1_rw override lazy val depth = BigInt(1024) override lazy val memWidth = 128 override lazy val libWidth = 32 - override lazy val memMaskGran = Some(8) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(8) + override lazy val libMaskGran: Option[Int] = Some(1) compileExecuteAndTest(mem, lib, v, output) } @@ -328,8 +328,8 @@ class SplitWidth1024x16_memGran_4_libGran_1_rw override lazy val depth = BigInt(1024) override lazy val memWidth = 16 override lazy val libWidth = 8 - override lazy val memMaskGran = Some(4) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(4) + override lazy val libMaskGran: Option[Int] = Some(1) compileExecuteAndTest(mem, lib, v, output) } @@ -341,8 +341,8 @@ class SplitWidth1024x16_memGran_2_libGran_1_rw override lazy val depth = BigInt(1024) override lazy val memWidth = 16 override lazy val libWidth = 8 - override lazy val memMaskGran = Some(2) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(2) + override lazy val libMaskGran: Option[Int] = Some(1) compileExecuteAndTest(mem, lib, v, output) } @@ -354,8 +354,8 @@ class SplitWidth1024x16_memGran_16_libGran_1_rw override lazy val depth = BigInt(1024) override lazy val memWidth = 16 override lazy val libWidth = 8 - override lazy val memMaskGran = Some(16) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(16) + override lazy val libMaskGran: Option[Int] = Some(1) compileExecuteAndTest(mem, lib, v, output) } @@ -366,7 +366,7 @@ class SplitWidth1024x16_libGran_8_rw extends MacroCompilerSpec with HasSRAMGener override lazy val depth = BigInt(1024) override lazy val memWidth = 16 override lazy val libWidth = 8 - override lazy val libMaskGran = Some(8) + override lazy val libMaskGran: Option[Int] = Some(8) compileExecuteAndTest(mem, lib, v, output) } @@ -375,7 +375,7 @@ class SplitWidth1024x16_libGran_1_rw extends MacroCompilerSpec with HasSRAMGener override lazy val depth = BigInt(1024) override lazy val memWidth = 16 override lazy val libWidth = 8 - override lazy val libMaskGran = Some(1) + override lazy val libMaskGran: Option[Int] = Some(1) compileExecuteAndTest(mem, lib, v, output) } @@ -389,8 +389,8 @@ class SplitWidth1024x16_memGran_8_libGran_2_rw override lazy val depth = BigInt(1024) override lazy val memWidth = 16 override lazy val libWidth = 8 - override lazy val memMaskGran = Some(8) - override lazy val libMaskGran = Some(2) + override lazy val memMaskGran: Option[Int] = Some(8) + override lazy val libMaskGran: Option[Int] = Some(2) compileExecuteAndTest(mem, lib, v, output) } @@ -404,8 +404,8 @@ class SplitWidth1024x16_memGran_9_libGran_1_rw override lazy val depth = BigInt(1024) override lazy val memWidth = 16 override lazy val libWidth = 8 - override lazy val memMaskGran = Some(9) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(9) + override lazy val libMaskGran: Option[Int] = Some(1) (it should "be enabled when non-power of two masks are supported").is(pending) //~ compile(mem, lib, v, false) @@ -424,7 +424,7 @@ class SplitWidth1024x32_readEnable_Lib override lazy val memWidth = 32 override lazy val libWidth = 8 - override def generateLibSRAM() = { + override def generateLibSRAM(): SRAMMacro = { SRAMMacro( name = lib_name, width = libWidth, @@ -492,7 +492,7 @@ class SplitWidth1024x32_readEnable_Mem override lazy val memWidth = 32 override lazy val libWidth = 8 - override def generateMemSRAM() = { + override def generateMemSRAM(): SRAMMacro = { SRAMMacro( name = mem_name, width = memWidth, @@ -528,7 +528,7 @@ class SplitWidth1024x32_readEnable_LibMem override lazy val memWidth = 32 override lazy val libWidth = 8 - override def generateLibSRAM() = { + override def generateLibSRAM(): SRAMMacro = { SRAMMacro( name = lib_name, width = libWidth, @@ -549,7 +549,7 @@ class SplitWidth1024x32_readEnable_LibMem ) } - override def generateMemSRAM() = { + override def generateMemSRAM(): SRAMMacro = { SRAMMacro( name = mem_name, width = memWidth, diff --git a/src/test/scala/barstools/macros/SpecificExamples.scala b/src/test/scala/barstools/macros/SpecificExamples.scala index 01d08de7..b0e2467f 100644 --- a/src/test/scala/barstools/macros/SpecificExamples.scala +++ b/src/test/scala/barstools/macros/SpecificExamples.scala @@ -1,7 +1,8 @@ // See LICENSE for license details. package barstools.macros -import mdf.macrolib._ +import firrtl.FileUtils +import mdf.macrolib.{Constant, MacroExtraPort, SRAMMacro} // Specific one-off tests to run, not created by a generator. @@ -17,7 +18,7 @@ class GenerateSomeVerilog extends MacroCompilerSpec with HasSRAMGenerator with H } it should "generate non-empty verilog" in { - val verilog = scala.io.Source.fromFile(vPrefix + "/" + v).getLines().mkString("\n") + val verilog = FileUtils.getText(vPrefix + "/" + v) verilog.isEmpty shouldBe false } } @@ -29,7 +30,7 @@ class WriteEnableTest extends MacroCompilerSpec with HasSRAMGenerator { override val libPrefix = "src/test/resources" - val memSRAMs = mdf.macrolib.Utils + val memSRAMs: Seq[mdf.macrolib.Macro] = mdf.macrolib.Utils .readMDFFromString(""" [ { "type" : "sram", @@ -53,7 +54,7 @@ class WriteEnableTest extends MacroCompilerSpec with HasSRAMGenerator { } ], "family" : "1rw" } ] -""").getOrElse(List()) +""").getOrElse(Seq()) writeToMem(mem, memSRAMs) @@ -101,7 +102,7 @@ class MaskPortTest extends MacroCompilerSpec with HasSRAMGenerator { override val libPrefix = "src/test/resources" - val memSRAMs = mdf.macrolib.Utils + val memSRAMs: Seq[mdf.macrolib.Macro] = mdf.macrolib.Utils .readMDFFromString(""" [ { "type" : "sram", @@ -175,7 +176,7 @@ circuit cc_dir_ext : defname = fake_mem """ - it should "compile, exectue, and test" in { + it should "compile, execute, and test" in { compileExecuteAndTest(mem, lib, v, output) } } @@ -187,7 +188,7 @@ class BOOMTest extends MacroCompilerSpec with HasSRAMGenerator { override val libPrefix = "src/test/resources" - val memSRAMs = mdf.macrolib.Utils + val memSRAMs: Seq[mdf.macrolib.Macro] = mdf.macrolib.Utils .readMDFFromString(""" [ { "type" : "sram", @@ -1461,7 +1462,7 @@ class RocketChipTest extends MacroCompilerSpec with HasSRAMGenerator { ) ) - val memSRAMs = mdf.macrolib.Utils + val memSRAMs: Seq[mdf.macrolib.Macro] = mdf.macrolib.Utils .readMDFFromString(""" [ { diff --git a/src/test/scala/barstools/macros/SynFlops.scala b/src/test/scala/barstools/macros/SynFlops.scala index 0d39220e..16a3446c 100644 --- a/src/test/scala/barstools/macros/SynFlops.scala +++ b/src/test/scala/barstools/macros/SynFlops.scala @@ -4,27 +4,27 @@ package barstools.macros trait HasSynFlopsTestGenerator extends HasSimpleTestGenerator { this: MacroCompilerSpec with HasSRAMGenerator => - def generateFlops: String = { + def generateFlops(): String = { s""" - inst mem_0_0 of split_${lib_name} + inst mem_0_0 of split_$lib_name mem_0_0.${libPortPrefix}_clk <= ${libPortPrefix}_clk mem_0_0.${libPortPrefix}_addr <= ${libPortPrefix}_addr node ${libPortPrefix}_dout_0_0 = bits(mem_0_0.${libPortPrefix}_dout, ${libWidth - 1}, 0) mem_0_0.${libPortPrefix}_din <= bits(${libPortPrefix}_din, ${libWidth - 1}, 0) mem_0_0.${libPortPrefix}_write_en <= and(and(and(${libPortPrefix}_write_en, UInt<1>("h1")), UInt<1>("h1")), UInt<1>("h1")) node ${libPortPrefix}_dout_0 = ${libPortPrefix}_dout_0_0 - ${libPortPrefix}_dout <= mux(UInt<1>("h1"), ${libPortPrefix}_dout_0, UInt<${libWidth}>("h0")) + ${libPortPrefix}_dout <= mux(UInt<1>("h1"), ${libPortPrefix}_dout_0, UInt<$libWidth>("h0")) - module split_${lib_name} : - input ${libPortPrefix}_addr : UInt<${lib_addr_width}> + module split_$lib_name : + input ${libPortPrefix}_addr : UInt<$lib_addr_width> input ${libPortPrefix}_clk : Clock - input ${libPortPrefix}_din : UInt<${libWidth}> - output ${libPortPrefix}_dout : UInt<${libWidth}> + input ${libPortPrefix}_din : UInt<$libWidth> + output ${libPortPrefix}_dout : UInt<$libWidth> input ${libPortPrefix}_write_en : UInt<1> mem ram : - data-type => UInt<${libWidth}> - depth => ${libDepth} + data-type => UInt<$libWidth> + depth => $libDepth read-latency => 1 write-latency => 1 readwriter => RW_0 @@ -40,20 +40,24 @@ trait HasSynFlopsTestGenerator extends HasSimpleTestGenerator { } // If there is no lib, put the flops definition into the body. - abstract override def generateBody = { - if (this.isInstanceOf[HasNoLibTestGenerator]) generateFlops else super.generateBody + abstract override def generateBody(): String = { + if (this.isInstanceOf[HasNoLibTestGenerator]) { + generateFlops() + } else { + super.generateBody() + } } // If there is no lib, don't generate a footer, since the flops definition // will be in the body. - override def generateFooter = { + override def generateFooter(): String = { if (this.isInstanceOf[HasNoLibTestGenerator]) "" else s""" - module ${lib_name} : -${generateFooterPorts} + module $lib_name : +${generateFooterPorts()} -${generateFlops} +${generateFlops()} """ } @@ -67,7 +71,7 @@ class Synflops2048x8_noLib override lazy val memDepth = BigInt(2048) override lazy val memWidth = 8 - compileExecuteAndTest(mem, None, v, output, true) + compileExecuteAndTest(mem, None, v, output, synflops = true) } class Synflops2048x16_noLib @@ -78,7 +82,7 @@ class Synflops2048x16_noLib override lazy val memDepth = BigInt(2048) override lazy val memWidth = 16 - compileExecuteAndTest(mem, None, v, output, true) + compileExecuteAndTest(mem, None, v, output, synflops = true) } class Synflops8192x16_noLib @@ -89,7 +93,7 @@ class Synflops8192x16_noLib override lazy val memDepth = BigInt(8192) override lazy val memWidth = 16 - compileExecuteAndTest(mem, None, v, output, true) + compileExecuteAndTest(mem, None, v, output, synflops = true) } class Synflops2048x16_depth_Lib @@ -101,7 +105,7 @@ class Synflops2048x16_depth_Lib override lazy val libDepth = BigInt(1024) override lazy val width = 16 - compileExecuteAndTest(mem, lib, v, output, true) + compileExecuteAndTest(mem, lib, v, output, synflops = true) } class Synflops2048x64_width_Lib @@ -113,7 +117,7 @@ class Synflops2048x64_width_Lib override lazy val libWidth = 8 override lazy val depth = BigInt(1024) - compileExecuteAndTest(mem, lib, v, output, true) + compileExecuteAndTest(mem, lib, v, output, synflops = true) } class Synflops_SplitPorts_Read_Write @@ -127,7 +131,7 @@ class Synflops_SplitPorts_Read_Write override lazy val libDepth = BigInt(1024) override lazy val width = 8 - override def generateLibSRAM = SRAMMacro( + override def generateLibSRAM(): SRAMMacro = SRAMMacro( name = lib_name, width = width, depth = libDepth, @@ -138,7 +142,7 @@ class Synflops_SplitPorts_Read_Write ) ) - override def generateMemSRAM = SRAMMacro( + override def generateMemSRAM(): SRAMMacro = SRAMMacro( name = mem_name, width = width, depth = memDepth, @@ -149,7 +153,7 @@ class Synflops_SplitPorts_Read_Write ) ) - override def generateHeader = + override def generateHeader() = """ circuit target_memory : module target_memory : @@ -162,7 +166,7 @@ circuit target_memory : input outerA_write_en : UInt<1> """ - override def generateBody = + override def generateBody() = """ node outerB_addr_sel = bits(outerB_addr, 10, 10) reg outerB_addr_sel_reg : UInt<1>, outerB_clk with : @@ -190,7 +194,7 @@ circuit target_memory : outerB_dout <= mux(eq(outerB_addr_sel_reg, UInt<1>("h0")), outerB_dout_0, mux(eq(outerB_addr_sel_reg, UInt<1>("h1")), outerB_dout_1, UInt<8>("h0"))) """ - override def generateFooterPorts = + override def generateFooterPorts() = """ input innerA_addr : UInt<10> input innerA_clk : Clock @@ -201,7 +205,7 @@ circuit target_memory : input innerB_write_en : UInt<1> """ - override def generateFlops = + override def generateFlops() = """ inst mem_0_0 of split_awesome_lib_mem mem_0_0.innerB_clk <= innerB_clk @@ -243,7 +247,7 @@ circuit target_memory : """ "Non-masked split lib; split mem" should "syn flops fine" in { - compileExecuteAndTest(mem, lib, v, output, true) + compileExecuteAndTest(mem, lib, v, output, synflops = true) } } @@ -257,10 +261,10 @@ class Synflops_SplitPorts_MaskedMem_Read_MaskedWrite override lazy val memDepth = BigInt(2048) override lazy val libDepth = BigInt(1024) override lazy val width = 8 - override lazy val memMaskGran = Some(8) - override lazy val libMaskGran = Some(1) + override lazy val memMaskGran: Option[Int] = Some(8) + override lazy val libMaskGran: Option[Int] = Some(1) - override def generateLibSRAM = SRAMMacro( + override def generateLibSRAM(): SRAMMacro = SRAMMacro( name = lib_name, width = width, depth = libDepth, @@ -271,7 +275,7 @@ class Synflops_SplitPorts_MaskedMem_Read_MaskedWrite ) ) - override def generateMemSRAM = SRAMMacro( + override def generateMemSRAM(): SRAMMacro = SRAMMacro( name = mem_name, width = width, depth = memDepth, @@ -282,7 +286,7 @@ class Synflops_SplitPorts_MaskedMem_Read_MaskedWrite ) ) - override def generateHeader = + override def generateHeader() = """ circuit target_memory : module target_memory : @@ -296,7 +300,7 @@ circuit target_memory : input outerA_mask : UInt<1> """ - override def generateBody = + override def generateBody() = """ node outerB_addr_sel = bits(outerB_addr, 10, 10) reg outerB_addr_sel_reg : UInt<1>, outerB_clk with : @@ -326,7 +330,7 @@ circuit target_memory : outerB_dout <= mux(eq(outerB_addr_sel_reg, UInt<1>("h0")), outerB_dout_0, mux(eq(outerB_addr_sel_reg, UInt<1>("h1")), outerB_dout_1, UInt<8>("h0"))) """ - override def generateFooterPorts = + override def generateFooterPorts() = """ input innerA_addr : UInt<10> input innerA_clk : Clock @@ -338,7 +342,7 @@ circuit target_memory : input innerB_mask : UInt<8> """ - override def generateFlops = + override def generateFlops() = """ inst mem_0_0 of split_awesome_lib_mem inst mem_0_1 of split_awesome_lib_mem @@ -446,6 +450,6 @@ circuit target_memory : """ "masked split lib; masked split mem" should "syn flops fine" in { - compileExecuteAndTest(mem, lib, v, output, true) + compileExecuteAndTest(mem, lib, v, output, synflops = true) } } diff --git a/src/test/scala/barstools/tapeout/transforms/GenerateSpec.scala b/src/test/scala/barstools/tapeout/transforms/GenerateSpec.scala index b953d170..a4dcd780 100644 --- a/src/test/scala/barstools/tapeout/transforms/GenerateSpec.scala +++ b/src/test/scala/barstools/tapeout/transforms/GenerateSpec.scala @@ -17,7 +17,7 @@ class BlackBoxInverter extends ExtModule { val out = IO(Output(Bool())) } -class GenerateExampleModule extends MultiIOModule { +class GenerateExampleModule extends Module { val in = IO(Input(Bool())) val out = IO(Output(Bool())) @@ -30,7 +30,7 @@ class GenerateExampleModule extends MultiIOModule { out := reg } -class ToBeMadeExternal extends MultiIOModule { +class ToBeMadeExternal extends Module { val in = IO(Input(Bool())) val out = IO(Output(Bool())) @@ -39,7 +39,7 @@ class ToBeMadeExternal extends MultiIOModule { out := reg } -class GenerateExampleTester extends MultiIOModule { +class GenerateExampleTester extends Module { val success = IO(Output(Bool())) val mod = Module(new GenerateExampleModule)