diff --git a/macros/src/main/scala/MacroCompiler.scala b/macros/src/main/scala/MacroCompiler.scala index cb03d14f..fac8e309 100644 --- a/macros/src/main/scala/MacroCompiler.scala +++ b/macros/src/main/scala/MacroCompiler.scala @@ -68,7 +68,7 @@ object MacroCompilerAnnotation { * @param costMetric Cost metric to use * @param mode Compiler mode (see CompilerMode) */ - case class Params(mem: String, lib: Option[String], costMetric: CostMetric, mode: CompilerMode) + case class Params(mem: String, lib: Option[String], costMetric: CostMetric, mode: CompilerMode, useCompiler: Boolean) /** * Create a MacroCompilerAnnotation. @@ -142,15 +142,15 @@ class MacroCompilerPass(mems: Option[Seq[Macro]], } // Make sure we don't have a maskGran larger than the width of the memory. - assert (memPort.src.effectiveMaskGran <= memPort.src.width) - assert (libPort.src.effectiveMaskGran <= libPort.src.width) + assert (memPort.src.effectiveMaskGran <= memPort.src.width.get) + assert (libPort.src.effectiveMaskGran <= libPort.src.width.get) - val libWidth = libPort.src.width + val libWidth = libPort.src.width.get // Don't consider cases of maskGran == width as "masked" since those masks // effectively function as write-enable bits. - val memMask = if (memPort.src.effectiveMaskGran == memPort.src.width) None else memPort.src.maskGran - val libMask = if (libPort.src.effectiveMaskGran == libPort.src.width) None else libPort.src.maskGran + val memMask = if (memPort.src.effectiveMaskGran == memPort.src.width.get) None else memPort.src.maskGran + val libMask = if (libPort.src.effectiveMaskGran == libPort.src.width.get) None else libPort.src.maskGran (memMask, libMask) match { // Neither lib nor mem is masked. @@ -163,12 +163,12 @@ class MacroCompilerPass(mems: Option[Seq[Macro]], // Only the mem is masked. case (Some(p), None) => { - if (p % libPort.src.width == 0) { + 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. // e.g. lib width=4, mem maskGran={4, 8, 12, 16, ...} splitMemory(libWidth) - } else if (libPort.src.width % p == 0) { + } else if (libPort.src.width.get % p == 0) { // Lib width is a multiple of the mem mask. // Consider the case where mem mask = 4 but lib width = 8, unmasked. // We can still compile, but will need to waste the extra bits. @@ -176,13 +176,13 @@ class MacroCompilerPass(mems: Option[Seq[Macro]], } else { // No neat multiples. // We might still be able to compile extremely inefficiently. - if (p < libPort.src.width) { + if (p < libPort.src.width.get) { // Compile using mem mask as the effective width. (note that lib is not masked) // e.g. mem mask = 3, lib width = 8 splitMemory(memMask.get) } else { // e.g. mem mask = 13, lib width = 8 - System.err.println(s"Unmasked target memory: unaligned mem maskGran ${p} with lib (${lib.src.name}) width ${libPort.src.width} not supported") + System.err.println(s"Unmasked target memory: unaligned mem maskGran ${p} with lib (${lib.src.name}) width ${libPort.src.width.get} not supported") return None } } @@ -378,13 +378,13 @@ class MacroCompilerPass(mems: Option[Seq[Macro]], case Some(PolarizedPort(mem, _)) => /* Palmer: The bits from the outer memory's write mask that will be * used as the write mask for this inner memory. */ - if (libPort.src.effectiveMaskGran == libPort.src.width) { + if (libPort.src.effectiveMaskGran == libPort.src.width.get) { bits(WRef(mem), low / memPort.src.effectiveMaskGran) } else { require(isPowerOfTwo(libPort.src.effectiveMaskGran), "only powers of two masks supported for now") - val effectiveLibWidth = if (memPort.src.maskGran.get < libPort.src.effectiveMaskGran) memPort.src.maskGran.get else libPort.src.width - cat(((0 until libPort.src.width by libPort.src.effectiveMaskGran) map (i => { + val effectiveLibWidth = if (memPort.src.maskGran.get < libPort.src.effectiveMaskGran) memPort.src.maskGran.get else libPort.src.width.get + cat(((0 until libPort.src.width.get by libPort.src.effectiveMaskGran) map (i => { if (memPort.src.maskGran.get < libPort.src.effectiveMaskGran && i >= effectiveLibWidth) { // If the memMaskGran is smaller than the lib's gran, then // zero out the upper bits. @@ -398,7 +398,7 @@ class MacroCompilerPass(mems: Option[Seq[Macro]], /* If there is a lib mask port but no mem mask port, just turn on * all bits of the lib mask port. */ if (libPort.src.maskPort.isDefined) { - val width = libPort.src.width / libPort.src.effectiveMaskGran + val width = libPort.src.width.get / libPort.src.effectiveMaskGran val value = (BigInt(1) << width.toInt) - 1 UIntLiteral(value, IntWidth(width)) } else { @@ -525,7 +525,7 @@ class MacroCompilerPass(mems: Option[Seq[Macro]], // Run the cost function to evaluate this potential compile. costMetric.cost(mem, lib) match { case Some(newCost) => { - System.err.println(s"Cost of ${lib.src.name} for ${mem.src.name}: ${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 @@ -561,7 +561,7 @@ class MacroCompilerTransform extends Transform { def inputForm = MidForm def outputForm = MidForm def execute(state: CircuitState) = getMyAnnotations(state) match { - case Seq(MacroCompilerAnnotation(state.circuit.main, MacroCompilerAnnotation.Params(memFile, libFile, costMetric, mode))) => + case Seq(MacroCompilerAnnotation(state.circuit.main, MacroCompilerAnnotation.Params(memFile, libFile, costMetric, mode, useCompiler))) => if (mode == MacroCompilerAnnotation.FallbackSynflops) { throw new UnsupportedOperationException("Not implemented yet") } @@ -573,7 +573,10 @@ class MacroCompilerTransform extends Transform { } val libs: Option[Seq[Macro]] = mdf.macrolib.Utils.readMDFFromPath(libFile) match { case Some(x:Seq[mdf.macrolib.Macro]) => - Some(Utils.filterForSRAM(Some(x)) getOrElse(List()) map {new Macro(_)}) + if(useCompiler){ + findSRAMCompiler(Some(x)).map{x => buildSRAMMacros(x).map(new Macro(_)) } + } + else Some(Utils.filterForSRAM(Some(x)) getOrElse(List()) map {new Macro(_)}) case _ => None } val transforms = Seq( @@ -614,12 +617,14 @@ object MacroCompiler extends App { case object Firrtl extends MacroParam case object CostFunc extends MacroParam case object Mode extends MacroParam + case object UseCompiler extends MacroParam type MacroParamMap = Map[MacroParam, String] type CostParamMap = Map[String, String] val usage = Seq( "Options:", " -m, --macro-list: The set of macros to compile", " -l, --library: The set of macros that have blackbox instances", + " -u, --use-compiler: Flag, whether to use the memory compiler defined in library", " -v, --verilog: Verilog output", " -f, --firrtl: FIRRTL output (optional)", " -c, --cost-func: Cost function to use. Optional (default: \"default\")", @@ -638,6 +643,8 @@ object MacroCompiler extends App { parseArgs(map + (Macros -> value), costMap, tail) case ("-l" | "--library") :: value :: tail => parseArgs(map + (Library -> value), costMap, tail) + case ("-u" | "--use-compiler") :: tail => + parseArgs(map + (UseCompiler -> ""), costMap, tail) case ("-v" | "--verilog") :: value :: tail => parseArgs(map + (Verilog -> value), costMap, tail) case ("-f" | "--firrtl") :: value :: tail => @@ -669,7 +676,8 @@ object MacroCompiler extends App { MacroCompilerAnnotation.Params( params.get(Macros).get, params.get(Library), CostMetric.getCostMetric(params.getOrElse(CostFunc, "default"), costParams), - MacroCompilerAnnotation.stringToCompilerMode(params.getOrElse(Mode, "default")) + MacroCompilerAnnotation.stringToCompilerMode(params.getOrElse(Mode, "default")), + params.contains(UseCompiler) ) )) ) @@ -705,6 +713,7 @@ object MacroCompiler extends App { } } catch { case e: java.util.NoSuchElementException => + e.printStackTrace() println(usage) e.printStackTrace() sys.exit(1) diff --git a/macros/src/main/scala/Utils.scala b/macros/src/main/scala/Utils.scala index 78c5007b..ded5c53f 100644 --- a/macros/src/main/scala/Utils.scala +++ b/macros/src/main/scala/Utils.scala @@ -18,9 +18,9 @@ class FirrtlMacroPort(port: MacroPort) { val isWriter = port.input.nonEmpty && port.output.isEmpty val isReadWriter = port.input.nonEmpty && port.output.nonEmpty - val addrType = UIntType(IntWidth(ceilLog2(port.depth) max 1)) - val dataType = UIntType(IntWidth(port.width)) - val maskType = UIntType(IntWidth(port.width / port.effectiveMaskGran)) + val addrType = UIntType(IntWidth(ceilLog2(port.depth.get) max 1)) + val dataType = UIntType(IntWidth(port.width.get)) + val maskType = UIntType(IntWidth(port.width.get / port.effectiveMaskGran)) // Bundle representing this macro port. val tpe = BundleType(Seq( @@ -72,6 +72,33 @@ object Utils { case _ => None } } + def findSRAMCompiler(s: Option[Seq[mdf.macrolib.Macro]]): Option[mdf.macrolib.SRAMCompiler] = { + s match { + case Some(l:Seq[mdf.macrolib.Macro]) => + l collectFirst { + case x: mdf.macrolib.SRAMCompiler => x + } + case _ => None + } + } + def buildSRAMMacros(s: mdf.macrolib.SRAMCompiler): Seq[mdf.macrolib.SRAMMacro] = { + for (g <- s.groups; d <- g.depth; w <- g.width; vt <- g.vt) + yield mdf.macrolib.SRAMMacro(makeName(g, d, w, vt), w, d, g.family, g.ports.map(_.copy(width=Some(w), depth=Some(d))), g.extraPorts) + } + def makeName(g: mdf.macrolib.SRAMGroup, depth: Int, width: Int, vt: String): String = { + g.name.foldLeft(""){ (builder, next) => + next match { + case "depth"|"DEPTH" => builder + depth + case "width"|"WIDTH" => builder + width + case "vt" => builder + vt.toLowerCase + case "VT" => builder + vt.toUpperCase + case "family" => builder + g.family.toLowerCase + case "FAMILY" => builder + g.family.toUpperCase + case "mux"|"MUX" => builder + g.mux + case other => builder + other + } + } + } def and(e1: Expression, e2: Expression) = DoPrim(PrimOps.And, Seq(e1, e2), Nil, e1.tpe) diff --git a/macros/src/test/scala/MacroCompilerSpec.scala b/macros/src/test/scala/MacroCompilerSpec.scala index e3a72ec2..ade8d6ae 100644 --- a/macros/src/test/scala/MacroCompilerSpec.scala +++ b/macros/src/test/scala/MacroCompilerSpec.scala @@ -7,6 +7,8 @@ import firrtl.Utils.ceilLog2 import java.io.{File, StringWriter} abstract class MacroCompilerSpec extends org.scalatest.FlatSpec with org.scalatest.Matchers { + import scala.language.implicitConversions + implicit def String2SomeString(i: String): Option[String] = Some(i) val testDir: String = "test_run_dir/macros" new File(testDir).mkdirs // Make sure the testDir exists @@ -32,11 +34,12 @@ abstract class MacroCompilerSpec extends org.scalatest.FlatSpec with org.scalate } } - private def args(mem: String, lib: Option[String], v: String, synflops: Boolean) = + private def args(mem: String, lib: Option[String], v: String, synflops: Boolean, useCompiler: Boolean) = List("-m", mem.toString, "-v", v) ++ (lib match { case None => Nil case Some(l) => List("-l", l.toString) }) ++ costMetricCmdLine ++ - (if (synflops) List("--mode", "synflops") else Nil) + (if (synflops) List("--mode", "synflops") else Nil) ++ + (if (useCompiler) List("--use-compiler") else Nil) // Run the full compiler as if from the command line interface. // Generates the Verilog; useful in testing since an error will throw an @@ -44,12 +47,12 @@ abstract class MacroCompilerSpec extends org.scalatest.FlatSpec with org.scalate def compile(mem: String, lib: String, v: String, synflops: Boolean) { compile(mem, Some(lib), v, synflops) } - def compile(mem: String, lib: Option[String], v: String, synflops: Boolean) { + 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) - MacroCompiler.run(args(mem_full, lib_full, v_full, synflops)) + MacroCompiler.run(args(mem_full, lib_full, v_full, synflops, useCompiler)) } // Helper functions to write macro libraries to the given files. @@ -62,14 +65,11 @@ abstract class MacroCompilerSpec extends org.scalatest.FlatSpec with org.scalate } // Convenience function for running both compile, execute, and test at once. - def compileExecuteAndTest(mem: String, lib: Option[String], v: String, output: String, synflops: Boolean): Unit = { - compile(mem, lib, v, synflops) - val result = execute(mem, lib, synflops) + def compileExecuteAndTest(mem: String, lib: Option[String], v: String, output: String, synflops: Boolean = false, useCompiler: Boolean = false): Unit = { + compile(mem, lib, v, synflops, useCompiler) + val result = execute(mem, lib, synflops, useCompiler) test(result, output) } - def compileExecuteAndTest(mem: String, lib: String, v: String, output: String, synflops: Boolean = false): Unit = { - compileExecuteAndTest(mem, Some(lib), v, output, synflops) - } // Compare FIRRTL outputs after reparsing output with ScalaTest ("should be"). def test(result: Circuit, output: String): Unit = { @@ -79,21 +79,20 @@ abstract class MacroCompilerSpec extends org.scalatest.FlatSpec with org.scalate // Execute the macro compiler and returns a Circuit containing the output of // the memory compiler. - def execute(memFile: String, libFile: Option[String], synflops: Boolean): Circuit = { - execute(Some(memFile), libFile, synflops) - } - def execute(memFile: String, libFile: String, synflops: Boolean): Circuit = { - execute(Some(memFile), Some(libFile), synflops) - } - def execute(memFile: Option[String], libFile: Option[String], synflops: Boolean): Circuit = { + def execute(memFile: Option[String], libFile: Option[String], synflops: Boolean): Circuit = execute(memFile, libFile, synflops, 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) require(memFile.isDefined) val mems: Seq[Macro] = Utils.filterForSRAM(mdf.macrolib.Utils.readMDFFromPath(mem_full)).get map (new Macro(_)) - val libs: Option[Seq[Macro]] = Utils.filterForSRAM(mdf.macrolib.Utils.readMDFFromPath(lib_full)) match { - case Some(x) => Some(x map (new Macro(_))) - case None => None + val libs: Option[Seq[Macro]] = if(useCompiler) { + Utils.findSRAMCompiler(mdf.macrolib.Utils.readMDFFromPath(lib_full)).map{x => Utils.buildSRAMMacros(x).map(new Macro(_)) } + } else { + Utils.filterForSRAM(mdf.macrolib.Utils.readMDFFromPath(lib_full)) match { + case Some(x) => Some(x map (new Macro(_))) + case None => None + } } val macros = mems map (_.blackbox) val circuit = Circuit(NoInfo, macros, macros.last.name) @@ -105,6 +104,7 @@ abstract class MacroCompilerSpec extends org.scalatest.FlatSpec with org.scalate result } + // Helper method to deal with String + Option[String] private def concat(a: String, b: String): String = {a + "/" + b} private def concat(a: String, b: Option[String]): Option[String] = { @@ -118,12 +118,16 @@ abstract class MacroCompilerSpec extends org.scalatest.FlatSpec with org.scalate // A collection of standard SRAM generators. trait HasSRAMGenerator { import mdf.macrolib._ + import scala.language.implicitConversions + implicit def Int2SomeInt(i: Int): Option[Int] = Some(i) + // Generate a standard (read/write/combo) port for testing. + // Helper methods for optional width argument def generateTestPort( prefix: String, - width: Int, - depth: Int, + width: Option[Int], + depth: Option[Int], maskGran: Option[Int] = None, read: Boolean, readEnable: Boolean = false, @@ -133,55 +137,69 @@ trait HasSRAMGenerator { val realPrefix = if (prefix == "") "" else prefix + "_" MacroPort( - address=PolarizedPort(name=realPrefix + "addr", polarity=ActiveHigh), - clock=PolarizedPort(name=realPrefix + "clk", polarity=PositiveEdge), + address = PolarizedPort(name = realPrefix + "addr", polarity = ActiveHigh), + clock = PolarizedPort(name = realPrefix + "clk", polarity = PositiveEdge), - readEnable=if (readEnable) Some(PolarizedPort(name=realPrefix + "read_en", polarity=ActiveHigh)) else None, - writeEnable=if (writeEnable) Some(PolarizedPort(name=realPrefix + "write_en", polarity=ActiveHigh)) else None, + readEnable = if (readEnable) Some(PolarizedPort(name = realPrefix + "read_en", polarity = ActiveHigh)) else None, + writeEnable = if (writeEnable) Some(PolarizedPort(name = realPrefix + "write_en", polarity = ActiveHigh)) else None, - output=if (read) Some(PolarizedPort(name=realPrefix + "dout", polarity=ActiveHigh)) else None, - input=if (write) Some(PolarizedPort(name=realPrefix + "din", polarity=ActiveHigh)) else None, + 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)) + maskPort = maskGran match { + case Some(x: Int) => Some(PolarizedPort(name = realPrefix + "mask", polarity = ActiveHigh)) case _ => None }, - maskGran=maskGran, + maskGran = maskGran, - width=width, depth=depth // These numbers don't matter here. + width = width, depth = depth // These numbers don't matter here. ) } // Generate a read port for testing. - def generateReadPort(prefix: String, width: Int, depth: Int, readEnable: Boolean = false): MacroPort = { - generateTestPort(prefix, width, depth, write=false, read=true, readEnable=readEnable) + def generateReadPort(prefix: String, width: Option[Int], depth: Option[Int], readEnable: Boolean = false): MacroPort = { + generateTestPort(prefix, width, depth, write = false, read = true, readEnable = readEnable) } // Generate a write port for testing. - def generateWritePort(prefix: String, width: Int, depth: Int, maskGran: Option[Int] = None, writeEnable: Boolean = true): MacroPort = { - generateTestPort(prefix, width, depth, maskGran=maskGran, write=true, read=false, writeEnable=writeEnable) + def generateWritePort(prefix: String, width: Option[Int], depth: Option[Int], maskGran: Option[Int] = None, writeEnable: Boolean = true): MacroPort = { + generateTestPort(prefix, width, depth, maskGran = maskGran, write = true, read = false, writeEnable = writeEnable) } // Generate a simple read-write port for testing. - def generateReadWritePort(prefix: String, width: Int, depth: Int, maskGran: Option[Int] = None): MacroPort = { + def generateReadWritePort(prefix: String, width: Option[Int], depth: Option[Int], maskGran: Option[Int] = None): MacroPort = { generateTestPort( - prefix, width, depth, maskGran=maskGran, - write=true, writeEnable=true, - read=true, readEnable=false + prefix, width, depth, maskGran = maskGran, + write = true, writeEnable = true, + read = true, readEnable = false ) } // Generate a "simple" SRAM (active high/positive edge, 1 read-write port). def generateSRAM(name: String, prefix: String, width: Int, depth: Int, maskGran: Option[Int] = None, extraPorts: Seq[MacroExtraPort] = List()): SRAMMacro = { SRAMMacro( - name=name, - width=width, - depth=depth, - family="1rw", - ports=Seq(generateReadWritePort(prefix, width, depth, maskGran)), - extraPorts=extraPorts + name = name, + width = width, + depth = depth, + family = "1rw", + ports = Seq(generateReadWritePort(prefix, width, depth, maskGran)), + extraPorts = extraPorts ) } + + // 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()): SRAMGroup = { + SRAMGroup(Seq("mygroup_", "width", "x", "depth", "_", "VT"), "1rw", Seq("svt", "lvt", "ulvt"), mux, depth, width, Seq(generateReadWritePort(prefix, None, None, maskGran))) + } + + // 'vt': ('svt','lvt','ulvt'), 'mux': 2, 'depth': range(16,513,8), 'width': range(8,289,2), 'ports': 1 + // 'vt': ('svt','lvt','ulvt'), 'mux': 4, 'depth': range(32,1025,16), 'width': range(4,145), 'ports': 1} + def generateSRAMCompiler(name: String, prefix: String): mdf.macrolib.SRAMCompiler = { + SRAMCompiler(name, Seq( + generateSimpleSRAMGroup(prefix, 2, Range(16, 512, 8), Range(8, 288, 2)), + generateSimpleSRAMGroup(prefix, 4, Range(32, 1024, 16), Range(4, 144, 1)) + )) + } } // Generic "simple" test generator. @@ -192,6 +210,7 @@ trait HasSimpleTestGenerator { // Override these with "override lazy val". // Why lazy? These are used in the constructor here so overriding non-lazily // would be too late. + def useCompiler: Boolean = false def memWidth: Int def libWidth: Int def memDepth: Int @@ -224,10 +243,10 @@ trait HasSimpleTestGenerator { val lib = s"lib-${generatorType}${extraTagPrefixed}.json" val v = s"${generatorType}${extraTagPrefixed}.v" - val mem_name = "target_memory" + lazy val mem_name = "target_memory" val mem_addr_width = ceilLog2(memDepth) - val lib_name = "awesome_lib_mem" + lazy val lib_name = "awesome_lib_mem" val lib_addr_width = ceilLog2(libDepth) // Override these to change the port prefixes if needed. @@ -258,8 +277,8 @@ trait HasSimpleTestGenerator { // 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. - val lastWidthBits = if (memWidth % usableLibWidth == 0) usableLibWidth else (memWidth % usableLibWidth) - val selectBits = mem_addr_width - lib_addr_width + lazy val lastWidthBits = if (memWidth % usableLibWidth == 0) usableLibWidth else (memWidth % usableLibWidth) + lazy val selectBits = mem_addr_width - lib_addr_width /** * Convenience function to generate a mask statement. @@ -410,3 +429,4 @@ trait HasNoLibTestGenerator extends HasSimpleTestGenerator { // If there is no lib, don't generate a body. override def generateBody = "" } + diff --git a/macros/src/test/scala/SRAMCompiler.scala b/macros/src/test/scala/SRAMCompiler.scala new file mode 100644 index 00000000..ea6667e9 --- /dev/null +++ b/macros/src/test/scala/SRAMCompiler.scala @@ -0,0 +1,22 @@ +package barstools.macros + +import mdf.macrolib._ + +class SRAMCompiler extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator { + val compiler = generateSRAMCompiler("awesome", "A") + val verilog = s"v-SRAMCompiler.v" + override lazy val depth = 16 + override lazy val memWidth = 8 + override lazy val libWidth = 8 + override lazy val mem_name = "mymem" + override lazy val memPortPrefix = "X" + override lazy val lib_name = "mygroup_8x16_SVT" + override lazy val libPortPrefix = "A" + + writeToLib(lib, Seq(compiler)) + + + writeToMem(mem, Seq(generateSRAM("mymem", "X", 8, 16))) + + compileExecuteAndTest(mem, Some(lib), verilog, output=output, false, true) +} diff --git a/macros/src/test/scala/SimpleSplitDepth.scala b/macros/src/test/scala/SimpleSplitDepth.scala index 9d1c6dcd..6a623447 100644 --- a/macros/src/test/scala/SimpleSplitDepth.scala +++ b/macros/src/test/scala/SimpleSplitDepth.scala @@ -20,27 +20,27 @@ trait HasSimpleDepthTestGenerator extends HasSimpleTestGenerator { if (selectBits > 0) { output.append ( s""" - node outer_addr_sel = bits(outer_addr, ${mem_addr_width - 1}, $lib_addr_width) - reg outer_addr_sel_reg : UInt<${selectBits}>, outer_clk with : - reset => (UInt<1>("h0"), outer_addr_sel_reg) - outer_addr_sel_reg <= mux(UInt<1>("h1"), outer_addr_sel, outer_addr_sel_reg) + node ${memPortPrefix}_addr_sel = bits(${memPortPrefix}_addr, ${mem_addr_width - 1}, $lib_addr_width) + 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) { val maskStatement = generateMaskStatement(0, i) - val enableIdentifier = if (selectBits > 0) s"""eq(outer_addr_sel, UInt<${selectBits}>("h${i.toHexString}"))""" else "UInt<1>(\"h1\")" + val enableIdentifier = if (selectBits > 0) s"""eq(${memPortPrefix}_addr_sel, UInt<${selectBits}>("h${i.toHexString}"))""" else "UInt<1>(\"h1\")" output.append( s""" - inst mem_${i}_0 of awesome_lib_mem - mem_${i}_0.lib_clk <= outer_clk - mem_${i}_0.lib_addr <= outer_addr - node outer_dout_${i}_0 = bits(mem_${i}_0.lib_dout, ${width - 1}, 0) - mem_${i}_0.lib_din <= bits(outer_din, ${width - 1}, 0) + 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.lib_write_en <= and(and(outer_write_en, UInt<1>("h1")), ${enableIdentifier}) - node outer_dout_${i} = outer_dout_${i}_0 + mem_${i}_0.${libPortPrefix}_write_en <= and(and(${memPortPrefix}_write_en, UInt<1>("h1")), ${enableIdentifier}) + node ${memPortPrefix}_dout_${i} = ${memPortPrefix}_dout_${i}_0 """ ) } @@ -48,16 +48,16 @@ s""" if (i > depthInstances - 1) { "UInt<1>(\"h0\")" } else { - "mux(eq(outer_addr_sel_reg, UInt<%d>(\"h%s\")), outer_dout_%d, %s)".format( + s"""mux(eq(${memPortPrefix}_addr_sel_reg, UInt<%d>("h%s")), ${memPortPrefix}_dout_%d, %s)""".format( selectBits, i.toHexString, i, generate_outer_dout_tree(i + 1, depthInstances) ) } } - output append " outer_dout <= " + output append s" ${memPortPrefix}_dout <= " if (selectBits > 0) { output append generate_outer_dout_tree(0, depthInstances) } else { - output append """mux(UInt<1>("h1"), outer_dout_0, UInt<1>("h0"))""" + output append s"""mux(UInt<1>("h1"), ${memPortPrefix}_dout_0, UInt<1>("h0"))""" } output.toString diff --git a/macros/src/test/scala/SimpleSplitWidth.scala b/macros/src/test/scala/SimpleSplitWidth.scala index f9835bd4..1096e417 100644 --- a/macros/src/test/scala/SimpleSplitWidth.scala +++ b/macros/src/test/scala/SimpleSplitWidth.scala @@ -40,28 +40,28 @@ trait HasSimpleWidthTestGenerator extends HasSimpleTestGenerator { } else """UInt<1>("h1")""" s""" - mem_0_${i}.lib_clk <= outer_clk - mem_0_${i}.lib_addr <= outer_addr - node outer_dout_0_${i} = bits(mem_0_${i}.lib_dout, ${myMemWidth - 1}, 0) - mem_0_${i}.lib_din <= bits(outer_din, ${myBaseBit + myMemWidth - 1}, ${myBaseBit}) + 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}.lib_write_en <= and(and(outer_write_en, ${writeEnableBit}), UInt<1>("h1")) + mem_0_${i}.${libPortPrefix}_write_en <= and(and(${memPortPrefix}_write_en, ${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"outer_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 outer_dout_0 = ${catStmt} + node ${memPortPrefix}_dout_0 = ${catStmt} """ } output append -""" - outer_dout <= mux(UInt<1>("h1"), outer_dout_0, UInt<1>("h0")) +s""" + ${memPortPrefix}_dout <= mux(UInt<1>("h1"), ${memPortPrefix}_dout_0, UInt<1>("h0")) """ output.toString } @@ -398,7 +398,7 @@ class SplitWidth1024x32_readEnable_Lib extends MacroCompilerSpec with HasSRAMGen depth=libDepth, family="1rw", ports=Seq(generateTestPort( - "lib", libWidth, libDepth, maskGran=libMaskGran, + "lib", Some(libWidth), Some(libDepth), maskGran=libMaskGran, write=true, writeEnable=true, read=true, readEnable=true )) @@ -456,7 +456,7 @@ class SplitWidth1024x32_readEnable_Mem extends MacroCompilerSpec with HasSRAMGen depth=memDepth, family="1rw", ports=Seq(generateTestPort( - "outer", memWidth, memDepth, maskGran=memMaskGran, + "outer", Some(memWidth), Some(memDepth), maskGran=memMaskGran, write=true, writeEnable=true, read=true, readEnable=true )) @@ -482,7 +482,7 @@ class SplitWidth1024x32_readEnable_LibMem extends MacroCompilerSpec with HasSRAM depth=libDepth, family="1rw", ports=Seq(generateTestPort( - "lib", libWidth, libDepth, maskGran=libMaskGran, + "lib", Some(libWidth), Some(libDepth), maskGran=libMaskGran, write=true, writeEnable=true, read=true, readEnable=true )) @@ -496,7 +496,7 @@ class SplitWidth1024x32_readEnable_LibMem extends MacroCompilerSpec with HasSRAM depth=memDepth, family="1rw", ports=Seq(generateTestPort( - "outer", memWidth, memDepth, maskGran=memMaskGran, + "outer", Some(memWidth), Some(memDepth), maskGran=memMaskGran, write=true, writeEnable=true, read=true, readEnable=true )) diff --git a/mdf b/mdf index 2b5f3c16..2bc5a363 160000 --- a/mdf +++ b/mdf @@ -1 +1 @@ -Subproject commit 2b5f3c16daac6cd6eb9ed6aa2b9d836cd6e0648c +Subproject commit 2bc5a363e23e0276e8e33115e7d1a06c62e774ad