Reformat all scala files in macros

- Mostly this reformat comments and large argument lists to classes and methods
This commit is contained in:
chick
2021-02-03 17:50:36 -08:00
parent 93f86a5bc6
commit 68c3425493
15 changed files with 1743 additions and 1204 deletions

View File

@@ -2,15 +2,14 @@
package barstools.macros package barstools.macros
/** /** Trait which can calculate the cost of compiling a memory against a certain
* Trait which can calculate the cost of compiling a memory against a certain
* library memory macro using a cost function. * library memory macro using a cost function.
*/ */
// TODO: eventually explore compiling a single target memory using multiple // TODO: eventually explore compiling a single target memory using multiple
// different kinds of target memory. // different kinds of target memory.
trait CostMetric extends Serializable { trait CostMetric extends Serializable {
/**
* Cost function that returns the cost of compiling a memory using a certain /** Cost function that returns the cost of compiling a memory using a certain
* macro. * macro.
* *
* @param mem Memory macro to compile (target memory) * @param mem Memory macro to compile (target memory)
@@ -20,8 +19,7 @@ trait CostMetric extends Serializable {
*/ */
def cost(mem: Macro, lib: Macro): Option[Double] def cost(mem: Macro, lib: Macro): Option[Double]
/** /** Helper function to return the map of arguments (or an empty map if there are none).
* Helper function to return the map of arguments (or an empty map if there are none).
*/ */
def commandLineParams(): Map[String, String] def commandLineParams(): Map[String, String]
@@ -41,7 +39,8 @@ trait CostMetricCompanion {
/** Palmer's old metric. /** Palmer's old metric.
* TODO: figure out what is the difference between this metric and the current * TODO: figure out what is the difference between this metric and the current
* default metric and either revive or delete this metric. */ * default metric and either revive or delete this metric.
*/
object OldMetric extends CostMetric with CostMetricCompanion { object OldMetric extends CostMetric with CostMetricCompanion {
override def cost(mem: Macro, lib: Macro): Option[Double] = { override def cost(mem: Macro, lib: Macro): Option[Double] = {
/* Palmer: A quick cost function (that must be kept in sync with /* Palmer: A quick cost function (that must be kept in sync with
@@ -58,8 +57,7 @@ object OldMetric extends CostMetric with CostMetricCompanion {
override def construct(m: Map[String, String]) = OldMetric override def construct(m: Map[String, String]) = OldMetric
} }
/** /** An external cost function.
* An external cost function.
* Calls the specified path with paths to the JSON MDF representation of the mem * Calls the specified path with paths to the JSON MDF representation of the mem
* and lib macros. The external executable should print a Double. * and lib macros. The external executable should print a Double.
* None will be returned if the external executable does not print a valid * None will be returned if the external executable does not print a valid
@@ -115,11 +113,14 @@ object ExternalMetric extends CostMetricCompanion {
// TODO: write tests for this function to make sure it selects the right things // TODO: write tests for this function to make sure it selects the right things
object DefaultMetric extends CostMetric with CostMetricCompanion { object DefaultMetric extends CostMetric with CostMetricCompanion {
override def cost(mem: Macro, lib: Macro): Option[Double] = { override def cost(mem: Macro, lib: Macro): Option[Double] = {
val memMask = mem.src.ports map (_.maskGran) find (_.isDefined) map (_.get) val memMask = mem.src.ports.map(_.maskGran).find(_.isDefined).map(_.get)
val libMask = lib.src.ports map (_.maskGran) find (_.isDefined) map (_.get) val libMask = lib.src.ports.map(_.maskGran).find(_.isDefined).map(_.get)
val memWidth = (memMask, libMask) match { val memWidth = (memMask, libMask) match {
case (None, _) => mem.src.width 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), 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)) => { 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) if (m <= p) (mem.src.width / p) * math.ceil(p.toDouble / m) * m //Using multiple m's to create a p (integeraly)
else (mem.src.width / p) * m //Waste the extra maskbits else (mem.src.width / p) * m //Waste the extra maskbits
@@ -148,7 +149,8 @@ object MacroCompilerUtil {
// Adapted from https://stackoverflow.com/a/134918 // Adapted from https://stackoverflow.com/a/134918
/** Serialize an arbitrary object to String. /** Serialize an arbitrary object to String.
* Used to pass structured values through as an annotation. */ * Used to pass structured values through as an annotation.
*/
def objToString(o: Serializable): String = { def objToString(o: Serializable): String = {
val baos: ByteArrayOutputStream = new ByteArrayOutputStream val baos: ByteArrayOutputStream = new ByteArrayOutputStream
val oos: ObjectOutputStream = new ObjectOutputStream(baos) val oos: ObjectOutputStream = new ObjectOutputStream(baos)
@@ -168,6 +170,7 @@ object MacroCompilerUtil {
} }
object CostMetric { object CostMetric {
/** Define some default metric. */ /** Define some default metric. */
val default: CostMetric = DefaultMetric val default: CostMetric = DefaultMetric
@@ -178,8 +181,7 @@ object CostMetric {
registerCostMetric(ExternalMetric) registerCostMetric(ExternalMetric)
registerCostMetric(DefaultMetric) registerCostMetric(DefaultMetric)
/** /** Register a cost metric.
* Register a cost metric.
* @param createFuncHelper Companion object to fetch the name and construct * @param createFuncHelper Companion object to fetch the name and construct
* the metric. * the metric.
*/ */

View File

@@ -1,7 +1,6 @@
// See LICENSE for license details. // See LICENSE for license details.
/** /** Terminology note:
* Terminology note:
* mem - target memory to compile, in design (e.g. Mem() in rocket) * mem - target memory to compile, in design (e.g. Mem() in rocket)
* lib - technology SRAM(s) to use to compile mem * lib - technology SRAM(s) to use to compile mem
*/ */
@@ -29,33 +28,35 @@ case class MacroCompilerAnnotation(content: String) extends NoTargetAnnotation {
def params: Params = MacroCompilerUtil.objFromString(content).asInstanceOf[Params] def params: Params = MacroCompilerUtil.objFromString(content).asInstanceOf[Params]
} }
/** The MacroCompilerAnnotation to trigger the macro compiler.
/**
* The MacroCompilerAnnotation to trigger the macro compiler.
* Note that this annotation does NOT actually target any modules for * Note that this annotation does NOT actually target any modules for
* compilation. It simply holds all the settings for the memory compiler. The * compilation. It simply holds all the settings for the memory compiler. The
* actual selection of which memories to compile is set in the Params. * actual selection of which memories to compile is set in the Params.
* *
* To use, simply annotate the entire circuit itself with this annotation and * To use, simply annotate the entire circuit itself with this annotation and
* include [[MacroCompilerTransform]]. * include [[MacroCompilerTransform]].
*
*/ */
object MacroCompilerAnnotation { object MacroCompilerAnnotation {
/** Macro compiler mode. */ /** Macro compiler mode. */
sealed trait CompilerMode sealed trait CompilerMode
/** Strict mode - must compile all memories or error out. */ /** Strict mode - must compile all memories or error out. */
case object Strict extends CompilerMode case object Strict extends CompilerMode
/** Synflops mode - compile all memories with synflops (do not map to lib at all). */ /** Synflops mode - compile all memories with synflops (do not map to lib at all). */
case object Synflops extends CompilerMode case object Synflops extends CompilerMode
/** CompileAndSynflops mode - compile all memories and create mock versions of the target libs with synflops. */ /** CompileAndSynflops mode - compile all memories and create mock versions of the target libs with synflops. */
case object CompileAndSynflops extends CompilerMode case object CompileAndSynflops extends CompilerMode
/** FallbackSynflops - compile all memories to SRAM when possible and fall back to synflops if a memory fails. * */ /** FallbackSynflops - compile all memories to SRAM when possible and fall back to synflops if a memory fails. * */
case object FallbackSynflops extends CompilerMode case object FallbackSynflops extends CompilerMode
/** CompileAvailable - compile what is possible and do nothing with uncompiled memories. * */ /** CompileAvailable - compile what is possible and do nothing with uncompiled memories. * */
case object CompileAvailable extends CompilerMode case object CompileAvailable extends CompilerMode
/** /** The default mode for the macro compiler.
* The default mode for the macro compiler.
* TODO: Maybe set the default to FallbackSynflops (typical for * TODO: Maybe set the default to FallbackSynflops (typical for
* vlsi_mem_gen-like scripts) once it's implemented? * vlsi_mem_gen-like scripts) once it's implemented?
*/ */
@@ -65,20 +66,37 @@ object MacroCompilerAnnotation {
val options: Seq[(CompilerMode, String, String)] = Seq( val options: Seq[(CompilerMode, String, String)] = Seq(
(Default, "default", "Select the default option from below."), (Default, "default", "Select the default option from below."),
(Strict, "strict", "Compile all memories to library or return an error."), (Strict, "strict", "Compile all memories to library or return an error."),
(Synflops, "synflops", "Produces synthesizable flop-based memories for all memories (do not map to lib at all); likely useful for simulation purposes."), (
(CompileAndSynflops, "compileandsynflops", "Compile all memories and create mock versions of the target libs with synflops; likely also useful for simulation purposes."), Synflops,
(FallbackSynflops, "fallbacksynflops", "Compile all memories to library when possible and fall back to synthesizable flop-based memories when library synth is not possible."), "synflops",
(CompileAvailable, "compileavailable", "Compile all memories to library when possible and do nothing in case of errors. (default)") "Produces synthesizable flop-based memories for all memories (do not map to lib at all); likely useful for simulation purposes."
),
(
CompileAndSynflops,
"compileandsynflops",
"Compile all memories and create mock versions of the target libs with synflops; likely also useful for simulation purposes."
),
(
FallbackSynflops,
"fallbacksynflops",
"Compile all memories to library when possible and fall back to synthesizable flop-based memories when library synth is not possible."
),
(
CompileAvailable,
"compileavailable",
"Compile all memories to library when possible and do nothing in case of errors. (default)"
)
) )
/** Helper function to select a compiler mode. */ /** Helper function to select a compiler mode. */
def stringToCompilerMode(str: String): CompilerMode = options.collectFirst { case (mode, cmd, _) if cmd == str => mode } match { def stringToCompilerMode(str: String): CompilerMode = options.collectFirst {
case (mode, cmd, _) if cmd == str => mode
} match {
case Some(x) => x case Some(x) => x
case None => throw new IllegalArgumentException("No such compiler mode " + str) case None => throw new IllegalArgumentException("No such compiler mode " + str)
} }
/** /** Parameters associated to this MacroCompilerAnnotation.
* Parameters associated to this MacroCompilerAnnotation.
* *
* @param mem Path to memory lib * @param mem Path to memory lib
* @param memFormat Type of memory lib (Some("conf"), Some("mdf"), or None (defaults to mdf)) * @param memFormat Type of memory lib (Some("conf"), Some("mdf"), or None (defaults to mdf))
@@ -89,12 +107,18 @@ object MacroCompilerAnnotation {
* @param forceCompile Set of memories to force compiling to lib regardless of the mode * @param forceCompile Set of memories to force compiling to lib regardless of the mode
* @param forceSynflops Set of memories to force compiling as flops regardless of the mode * @param forceSynflops Set of memories to force compiling as flops regardless of the mode
*/ */
case class Params(mem: String, memFormat: Option[String], lib: Option[String], hammerIR: Option[String], case class Params(
costMetric: CostMetric, mode: CompilerMode, useCompiler: Boolean, mem: String,
forceCompile: Set[String], forceSynflops: Set[String]) memFormat: Option[String],
lib: Option[String],
hammerIR: Option[String],
costMetric: CostMetric,
mode: CompilerMode,
useCompiler: Boolean,
forceCompile: Set[String],
forceSynflops: Set[String])
/** /** Create a MacroCompilerAnnotation.
* Create a MacroCompilerAnnotation.
* @param c Top-level circuit name (see class description) * @param c Top-level circuit name (see class description)
* @param p Parameters (see above). * @param p Parameters (see above).
*/ */
@@ -103,12 +127,14 @@ object MacroCompilerAnnotation {
} }
class MacroCompilerPass(mems: Option[Seq[Macro]], class MacroCompilerPass(
mems: Option[Seq[Macro]],
libs: Option[Seq[Macro]], libs: Option[Seq[Macro]],
compilers: Option[SRAMCompiler], compilers: Option[SRAMCompiler],
hammerIR: Option[String], hammerIR: Option[String],
costMetric: CostMetric = CostMetric.default, costMetric: CostMetric = CostMetric.default,
mode: MacroCompilerAnnotation.CompilerMode = MacroCompilerAnnotation.Default) extends firrtl.passes.Pass { mode: MacroCompilerAnnotation.CompilerMode = MacroCompilerAnnotation.Default)
extends firrtl.passes.Pass {
// Helper function to check the legality of bitPairs. // Helper function to check the legality of bitPairs.
// e.g. ((0,21), (22,43)) is legal // e.g. ((0,21), (22,43)) is legal
// ((0,21), (22,21)) is illegal and will throw an assert // ((0,21), (22,21)) is illegal and will throw an assert
@@ -120,8 +146,7 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
}) })
} }
/** /** Calculate bit pairs.
* Calculate bit pairs.
* This is a list of submemories by width. * This is a list of submemories by width.
* The tuples are (lsb, msb) inclusive. * The tuples are (lsb, msb) inclusive.
* Example: (0, 7) and (8, 15) might be a split for a width=16 memory into two width=8 target memories. * Example: (0, 7) and (8, 15) might be a split for a width=16 memory into two width=8 target memories.
@@ -132,7 +157,7 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
* @return Bit pairs or empty list if there was an error. * @return Bit pairs or empty list if there was an error.
*/ */
private def calculateBitPairs(mem: Macro, lib: Macro): Seq[(BigInt, BigInt)] = { private def calculateBitPairs(mem: Macro, lib: Macro): Seq[(BigInt, BigInt)] = {
val pairedPorts = mem.sortedPorts zip lib.sortedPorts val pairedPorts = mem.sortedPorts.zip(lib.sortedPorts)
val bitPairs = ArrayBuffer[(BigInt, BigInt)]() val bitPairs = ArrayBuffer[(BigInt, BigInt)]()
var currentLSB: BigInt = 0 var currentLSB: BigInt = 0
@@ -203,7 +228,9 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
splitMemory(memMask.get) splitMemory(memMask.get)
} else { } else {
// e.g. mem mask = 13, lib width = 8 // 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.get} 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 Seq() return Seq()
} }
} }
@@ -266,9 +293,11 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
} }
def compile(mem: Macro, lib: Macro): Option[(Module, Macro)] = { def compile(mem: Macro, lib: Macro): Option[(Module, Macro)] = {
assert(mem.sortedPorts.lengthCompare(lib.sortedPorts.length) == 0, assert(
"mem and lib should have an equal number of ports") mem.sortedPorts.lengthCompare(lib.sortedPorts.length) == 0,
val pairedPorts = mem.sortedPorts zip lib.sortedPorts "mem and lib should have an equal number of ports"
)
val pairedPorts = mem.sortedPorts.zip(lib.sortedPorts)
// Width mapping. See calculateBitPairs. // Width mapping. See calculateBitPairs.
val bitPairs: Seq[(BigInt, BigInt)] = calculateBitPairs(mem, lib) val bitPairs: Seq[(BigInt, BigInt)] = calculateBitPairs(mem, lib)
@@ -287,7 +316,7 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
/* Palmer: If we've got a parallel memory then we've got to take the /* Palmer: If we've got a parallel memory then we've got to take the
* address bits into account. */ * address bits into account. */
if (mem.src.depth > lib.src.depth) { if (mem.src.depth > lib.src.depth) {
mem.src.ports foreach { port => mem.src.ports.foreach { port =>
val high = MacroCompilerMath.ceilLog2(mem.src.depth) val high = MacroCompilerMath.ceilLog2(mem.src.depth)
val low = MacroCompilerMath.ceilLog2(lib.src.depth) val low = MacroCompilerMath.ceilLog2(lib.src.depth)
val ref = WRef(port.address.name) val ref = WRef(port.address.name)
@@ -317,18 +346,18 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
// Create the instance. // Create the instance.
stmts += WDefInstance(NoInfo, name, lib.src.name, lib.tpe) stmts += WDefInstance(NoInfo, name, lib.src.name, lib.tpe)
// Connect extra ports of the lib. // Connect extra ports of the lib.
stmts ++= lib.extraPorts map { case (portName, portValue) => stmts ++= lib.extraPorts.map { case (portName, portValue) =>
Connect(NoInfo, WSubField(WRef(name), portName), portValue) Connect(NoInfo, WSubField(WRef(name), portName), portValue)
} }
} }
for ((memPort, libPort) <- pairedPorts) { for ((memPort, libPort) <- pairedPorts) {
val addrMatch = selects get memPort.src.address.name match { val addrMatch = selects.get(memPort.src.address.name) match {
case None => one case None => one
case Some(addr) => case Some(addr) =>
val index = UIntLiteral(i, IntWidth(bitWidth(addr.tpe))) val index = UIntLiteral(i, IntWidth(bitWidth(addr.tpe)))
DoPrim(PrimOps.Eq, Seq(addr, index), Nil, index.tpe) DoPrim(PrimOps.Eq, Seq(addr, index), Nil, index.tpe)
} }
val addrMatchReg = selectRegs get memPort.src.address.name match { val addrMatchReg = selectRegs.get(memPort.src.address.name) match {
case None => one case None => one
case Some(reg) => case Some(reg) =>
val index = UIntLiteral(i, IntWidth(bitWidth(reg.tpe))) val index = UIntLiteral(i, IntWidth(bitWidth(reg.tpe)))
@@ -341,29 +370,22 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
for (((low, high), j) <- bitPairs.zipWithIndex) { 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, def connectPorts2(mem: Expression, lib: String, polarity: Option[PortPolarity]): Statement =
lib: String,
polarity: Option[PortPolarity]): Statement =
Connect(NoInfo, WSubField(inst, lib), portToExpression(mem, polarity)) Connect(NoInfo, WSubField(inst, lib), portToExpression(mem, polarity))
def connectPorts(mem: Expression, def connectPorts(mem: Expression, lib: String, polarity: PortPolarity): Statement =
lib: String,
polarity: PortPolarity): Statement =
connectPorts2(mem, lib, Some(polarity)) connectPorts2(mem, lib, Some(polarity))
// Clock port mapping // Clock port mapping
/* Palmer: FIXME: I don't handle memories with read/write clocks yet. */ /* Palmer: FIXME: I don't handle memories with read/write clocks yet. */
/* Colin not all libPorts have clocks but all memPorts do*/ /* Colin not all libPorts have clocks but all memPorts do*/
libPort.src.clock.foreach { cPort => libPort.src.clock.foreach { cPort =>
stmts += connectPorts(WRef(memPort.src.clock.get.name), stmts += connectPorts(WRef(memPort.src.clock.get.name), cPort.name, cPort.polarity)
cPort.name, }
cPort.polarity) }
// Adress port mapping // Adress port mapping
/* Palmer: The address port to a memory is just the low-order bits of /* Palmer: The address port to a memory is just the low-order bits of
* the top address. */ * the top address. */
stmts += connectPorts(WRef(memPort.src.address.name), stmts += connectPorts(WRef(memPort.src.address.name), libPort.src.address.name, libPort.src.address.polarity)
libPort.src.address.name,
libPort.src.address.polarity)
// Output port mapping // Output port mapping
(memPort.src.output, libPort.src.output) match { (memPort.src.output, libPort.src.output) match {
@@ -385,8 +407,8 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
* port on the memory) then just don't worry about it, * port on the memory) then just don't worry about it,
* there's nothing to do. */ * there's nothing to do. */
case (Some(PolarizedPort(mem, _)), None) => case (Some(PolarizedPort(mem, _)), None) =>
System.err println "WARNING: Unable to match output ports on memory" 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 return None
} }
@@ -409,8 +431,8 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
* port on the memory) then just don't worry about it, * port on the memory) then just don't worry about it,
* there's nothing to do. */ * there's nothing to do. */
case (Some(PolarizedPort(mem, _)), None) => case (Some(PolarizedPort(mem, _)), None) =>
System.err println "WARNING: Unable to match input ports on memory" 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 return None
} }
@@ -429,12 +451,16 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
// Example: if we have a lib whose maskGran is 8 but our mem's maskGran is 4. // 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. // 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) val effectiveLibWidth =
if (usingLessThanLibMaskGran)
memPort.src.maskGran.get memPort.src.maskGran.get
else else
libPort.src.width.get libPort.src.width.get
cat(((0 until libPort.src.width.get by libPort.src.effectiveMaskGran) map (i => { cat(
(
(0 until libPort.src.width.get by libPort.src.effectiveMaskGran)
.map(i => {
if (usingLessThanLibMaskGran && i >= effectiveLibWidth) { if (usingLessThanLibMaskGran && i >= effectiveLibWidth) {
// If the memMaskGran is smaller than the lib's gran, then // If the memMaskGran is smaller than the lib's gran, then
// zero out the upper bits. // zero out the upper bits.
@@ -448,7 +474,10 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
bits(WRef(mem), (low + i) / memPort.src.effectiveMaskGran) bits(WRef(mem), (low + i) / memPort.src.effectiveMaskGran)
} }
} }
})).reverse) })
)
.reverse
)
} }
case None => case None =>
/* If there is a lib mask port but no mem mask port, just turn on /* If there is a lib mask port but no mem mask port, just turn on
@@ -501,7 +530,11 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
* implement the outer memory's collection of ports using what * implement the outer memory's collection of ports using what
* the inner memory has availiable. */ * the inner memory has availiable. */
((libPort.src.maskPort, libPort.src.writeEnable, libPort.src.chipEnable): @unchecked) match { ((libPort.src.maskPort, libPort.src.writeEnable, libPort.src.chipEnable): @unchecked) match {
case (Some(PolarizedPort(mask, mask_polarity)), Some(PolarizedPort(we, we_polarity)), Some(PolarizedPort(en, en_polarity))) => case (
Some(PolarizedPort(mask, mask_polarity)),
Some(PolarizedPort(we, we_polarity)),
Some(PolarizedPort(en, en_polarity))
) =>
/* Palmer: This is the simple option: every port exists. */ /* Palmer: This is the simple option: every port exists. */
stmts += connectPorts(memMask, mask, mask_polarity) stmts += connectPorts(memMask, mask, mask_polarity)
stmts += connectPorts(andAddrMatch(memWriteEnable), we, we_polarity) stmts += connectPorts(andAddrMatch(memWriteEnable), we, we_polarity)
@@ -509,8 +542,7 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
case (Some(PolarizedPort(mask, mask_polarity)), Some(PolarizedPort(we, we_polarity)), None) => case (Some(PolarizedPort(mask, mask_polarity)), Some(PolarizedPort(we, we_polarity)), None) =>
/* Palmer: If we don't have a chip enable but do have mask ports. */ /* Palmer: If we don't have a chip enable but do have mask ports. */
stmts += connectPorts(memMask, mask, mask_polarity) stmts += connectPorts(memMask, mask, mask_polarity)
stmts += connectPorts(andAddrMatch(and(memWriteEnable, memChipEnable)), stmts += connectPorts(andAddrMatch(and(memWriteEnable, memChipEnable)), we, we_polarity)
we, we_polarity)
case (None, Some(PolarizedPort(we, we_polarity)), chipEnable) => case (None, Some(PolarizedPort(we, we_polarity)), chipEnable) =>
if (bitWidth(memMask.tpe) == 1) { if (bitWidth(memMask.tpe) == 1) {
/* Palmer: If we're expected to provide mask ports without a /* Palmer: If we're expected to provide mask ports without a
@@ -518,13 +550,15 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
* write enable port instead of the mask port. */ * write enable port instead of the mask port. */
chipEnable match { chipEnable match {
case Some(PolarizedPort(en, en_polarity)) => { case Some(PolarizedPort(en, en_polarity)) => {
stmts += connectPorts(andAddrMatch(and(memWriteEnable, memMask)), stmts += connectPorts(andAddrMatch(and(memWriteEnable, memMask)), we, we_polarity)
we, we_polarity)
stmts += connectPorts(andAddrMatch(memChipEnable), en, en_polarity) stmts += connectPorts(andAddrMatch(memChipEnable), en, en_polarity)
} }
case _ => { case _ => {
stmts += connectPorts(andAddrMatch(and(and(memWriteEnable, memChipEnable), memMask)), stmts += connectPorts(
we, we_polarity) andAddrMatch(and(and(memWriteEnable, memChipEnable), memMask)),
we,
we_polarity
)
} }
} }
} else { } else {
@@ -541,7 +575,7 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
case Some(PolarizedPort(mem, _)) if cats.nonEmpty => 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)) stmts += DefNode(NoInfo, name, cat(cats.toSeq.reverse))
(outputs getOrElseUpdate (mem, ArrayBuffer[(Expression, Expression)]())) += (outputs.getOrElseUpdate(mem, ArrayBuffer[(Expression, Expression)]())) +=
(addrMatchReg -> WRef(name)) (addrMatchReg -> WRef(name))
case _ => case _ =>
} }
@@ -549,12 +583,14 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
} }
// Connect mem outputs // Connect mem outputs
val zeroOutputValue: Expression = UIntLiteral(0, IntWidth(mem.src.width)) val zeroOutputValue: Expression = UIntLiteral(0, IntWidth(mem.src.width))
mem.src.ports foreach { port => mem.src.ports.foreach { port =>
port.output match { port.output match {
case Some(PolarizedPort(mem, _)) => outputs get mem match { case Some(PolarizedPort(mem, _)) =>
outputs.get(mem) match {
case Some(select) => case Some(select) =>
val output = (select foldRight (zeroOutputValue)) { val output = (select.foldRight(zeroOutputValue)) { case ((cond, tval), fval) =>
case ((cond, tval), fval) => Mux(cond, tval, fval, fval.tpe) } Mux(cond, tval, fval, fval.tpe)
}
stmts += Connect(NoInfo, WRef(mem), output) stmts += Connect(NoInfo, WRef(mem), output)
case None => case None =>
} }
@@ -572,12 +608,11 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
// Try to compile each of the memories in mems. // Try to compile each of the memories in mems.
// The 'state' is c.modules, which is a list of all the firrtl modules // The 'state' is c.modules, which is a list of all the firrtl modules
// in the 'circuit'. // in the 'circuit'.
(mems foldLeft c.modules){ (modules, mem) => (mems.foldLeft(c.modules)) { (modules, mem) =>
val sram = mem.src val sram = mem.src
def groupMatchesMask(group: SRAMGroup, mem: SRAMMacro): Boolean = { def groupMatchesMask(group: SRAMGroup, mem: SRAMMacro): Boolean = {
val memMask = mem.ports map (_.maskGran) find (_.isDefined) map (_.get) val memMask = mem.ports.map(_.maskGran).find(_.isDefined).map(_.get)
val libMask = group.ports map (_.maskGran) find (_.isDefined) map (_.get) val libMask = group.ports.map(_.maskGran).find(_.isDefined).map(_.get)
(memMask, libMask) match { (memMask, libMask) match {
case (None, _) => true case (None, _) => true
case (Some(_), None) => false case (Some(_), None) => false
@@ -587,9 +622,13 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
// Add compiler memories that might map well to libs // Add compiler memories that might map well to libs
val compLibs = compilers match { val compLibs = compilers match {
case Some(SRAMCompiler(_, groups)) => { case Some(SRAMCompiler(_, groups)) => {
groups.filter(g => g.family == sram.family && groupMatchesMask(g, sram)).map( g => { groups
for(w <- g.width; d <- g.depth if((sram.width % w == 0) && (sram.depth % d == 0))) .filter(g => g.family == sram.family && groupMatchesMask(g, sram))
yield Seq(new Macro(buildSRAMMacro(g, d, w, g.vt.head))) .map(g => {
for {
w <- g.width
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() case None => Seq()
@@ -598,11 +637,11 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
// Try to compile mem against each lib in libs, keeping track of the // Try to compile mem against each lib in libs, keeping track of the
// best compiled version, external lib used, and cost. // best compiled version, external lib used, and cost.
val (best, cost) = (fullLibs foldLeft (None: Option[(Module, Macro)], Double.MaxValue)){ val (best, cost) = (fullLibs.foldLeft(None: Option[(Module, Macro)], Double.MaxValue)) {
case ((best, cost), lib) if mem.src.ports.size != lib.src.ports.size => 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 /* Palmer: FIXME: This just assumes the Chisel and vendor ports are in the same
* order, but I'm starting with what actually gets generated. */ * order, but I'm starting with what actually gets generated. */
System.err println s"INFO: unable to compile ${mem.src.name} using ${lib.src.name} port count must match" System.err.println(s"INFO: unable to compile ${mem.src.name} using ${lib.src.name} port count must match")
(best, cost) (best, cost)
case ((best, cost), lib) => case ((best, cost), lib) =>
// Run the cost function to evaluate this potential compile. // Run the cost function to evaluate this potential compile.
@@ -626,7 +665,9 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
best match { best match {
case None => { case None => {
if (mode == MacroCompilerAnnotation.Strict) if (mode == MacroCompilerAnnotation.Strict)
throw new MacroCompilerException(s"Target memory ${mem.src.name} could not be compiled and strict mode is activated - aborting.") throw new MacroCompilerException(
s"Target memory ${mem.src.name} could not be compiled and strict mode is activated - aborting."
)
else else
modules modules
} }
@@ -642,7 +683,7 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
} }
case None => 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 case _ => c.modules
@@ -657,13 +698,23 @@ class MacroCompilerTransform extends Transform {
def execute(state: CircuitState) = state.annotations.collect { case a: MacroCompilerAnnotation => a } match { def execute(state: CircuitState) = state.annotations.collect { case a: MacroCompilerAnnotation => a } match {
case Seq(anno: MacroCompilerAnnotation) => case Seq(anno: MacroCompilerAnnotation) =>
val MacroCompilerAnnotation.Params(memFile, memFileFormat, libFile, hammerIR, costMetric, mode, useCompiler, forceCompile, forceSynflops) = anno.params val MacroCompilerAnnotation.Params(
memFile,
memFileFormat,
libFile,
hammerIR,
costMetric,
mode,
useCompiler,
forceCompile,
forceSynflops
) = anno.params
if (mode == MacroCompilerAnnotation.FallbackSynflops) { if (mode == MacroCompilerAnnotation.FallbackSynflops) {
throw new UnsupportedOperationException("Not implemented yet") throw new UnsupportedOperationException("Not implemented yet")
} }
// Check that we don't have any modules both forced to compile and synflops. // 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 // Read, eliminate None, get only SRAM, make firrtl macro
val mems: Option[Seq[Macro]] = (memFileFormat match { val mems: Option[Seq[Macro]] = (memFileFormat match {
@@ -671,24 +722,22 @@ class MacroCompilerTransform extends Transform {
case _ => mdf.macrolib.Utils.readMDFFromPath(Some(memFile)) case _ => mdf.macrolib.Utils.readMDFFromPath(Some(memFile))
}) match { }) match {
case Some(x: Seq[mdf.macrolib.Macro]) => case Some(x: Seq[mdf.macrolib.Macro]) =>
Some(Utils.filterForSRAM(Some(x)) getOrElse(List()) map {new Macro(_)}) Some(Utils.filterForSRAM(Some(x)).getOrElse(List()).map { new Macro(_) })
case _ => None case _ => None
} }
val libs: Option[Seq[Macro]] = mdf.macrolib.Utils.readMDFFromPath(libFile) match { val libs: Option[Seq[Macro]] = mdf.macrolib.Utils.readMDFFromPath(libFile) match {
case Some(x: Seq[mdf.macrolib.Macro]) => case Some(x: Seq[mdf.macrolib.Macro]) =>
Some(Utils.filterForSRAM(Some(x)) getOrElse(List()) map {new Macro(_)}) Some(Utils.filterForSRAM(Some(x)).getOrElse(List()).map { new Macro(_) })
case _ => None case _ => None
} }
val compilers: Option[mdf.macrolib.SRAMCompiler] = mdf.macrolib.Utils.readMDFFromPath(libFile) match { val compilers: Option[mdf.macrolib.SRAMCompiler] = mdf.macrolib.Utils.readMDFFromPath(libFile) match {
case Some(x: Seq[mdf.macrolib.Macro]) => case Some(x: Seq[mdf.macrolib.Macro]) =>
if (useCompiler) { if (useCompiler) {
findSRAMCompiler(Some(x)) findSRAMCompiler(Some(x))
} } else None
else None
case _ => None case _ => None
} }
// Helper function to turn a set of mem names into a Seq[Macro]. // Helper function to turn a set of mem names into a Seq[Macro].
def setToSeqMacro(names: Set[String]): Seq[Macro] = { def setToSeqMacro(names: Set[String]): Seq[Macro] = {
names.toSeq.map(memName => mems.get.collectFirst { case m if m.src.name == memName => m }.get) names.toSeq.map(memName => mems.get.collectFirst { case m if m.src.name == memName => m }.get)
@@ -706,12 +755,16 @@ class MacroCompilerTransform extends Transform {
val transforms = Seq( val transforms = Seq(
new MacroCompilerPass(memCompile, libs, compilers, hammerIR, costMetric, mode), new MacroCompilerPass(memCompile, libs, compilers, hammerIR, costMetric, mode),
new SynFlopsPass(true, memSynflops ++ (if (mode == MacroCompilerAnnotation.CompileAndSynflops) { new SynFlopsPass(
true,
memSynflops ++ (if (mode == MacroCompilerAnnotation.CompileAndSynflops) {
libs.get libs.get
} else { } else {
Seq.empty Seq.empty
}))) })
(transforms foldLeft state) ((s, xform) => xform runTransform s).copy(form = outputForm) )
)
(transforms.foldLeft(state))((s, xform) => xform.runTransform(s)).copy(form = outputForm)
case _ => state case _ => state
} }
} }
@@ -729,7 +782,8 @@ class MacroCompilerOptimizations extends SeqTransform {
new firrtl.transforms.ConstantPropagation, new firrtl.transforms.ConstantPropagation,
passes.Legalize, passes.Legalize,
passes.SplitExpressions, passes.SplitExpressions,
passes.CommonSubexpressionElimination) passes.CommonSubexpressionElimination
)
} }
class MacroCompiler extends Compiler { class MacroCompiler extends Compiler {
@@ -756,8 +810,9 @@ object MacroCompiler extends App {
type MacroParamMap = Map[MacroParam, String] type MacroParamMap = Map[MacroParam, String]
type CostParamMap = Map[String, String] type CostParamMap = Map[String, String]
type ForcedMemories = (Set[String], Set[String]) type ForcedMemories = (Set[String], Set[String])
val modeOptions: Seq[String] = MacroCompilerAnnotation.options val modeOptions: Seq[String] = MacroCompilerAnnotation.options.map { case (_, cmd, description) =>
.map { case (_, cmd, description) => s" $cmd: $description" } s" $cmd: $description"
}
val usage: String = (Seq( val usage: String = (Seq(
"Options:", "Options:",
" -n, --macro-conf: The set of macros to compile in firrtl-generated conf format (exclusive with -m)", " -n, --macro-conf: The set of macros to compile in firrtl-generated conf format (exclusive with -m)",
@@ -772,10 +827,14 @@ object MacroCompiler extends App {
" --force-compile [mem]: Force the given memory to be compiled to target libs regardless of the mode", " --force-compile [mem]: Force the given memory to be compiled to target libs regardless of the mode",
" --force-synflops [mem]: Force the given memory to be compiled via synflops regardless of the mode", " --force-synflops [mem]: Force the given memory to be compiled via synflops regardless of the mode",
" --mode:" " --mode:"
) ++ modeOptions) mkString "\n" ) ++ modeOptions).mkString("\n")
def parseArgs(map: MacroParamMap, costMap: CostParamMap, forcedMemories: ForcedMemories, def parseArgs(
args: List[String]): (MacroParamMap, CostParamMap, ForcedMemories) = map: MacroParamMap,
costMap: CostParamMap,
forcedMemories: ForcedMemories,
args: List[String]
): (MacroParamMap, CostParamMap, ForcedMemories) =
args match { args match {
case Nil => (map, costMap, forcedMemories) case Nil => (map, costMap, forcedMemories)
case ("-n" | "--macro-conf") :: value :: tail => case ("-n" | "--macro-conf") :: value :: tail =>
@@ -809,11 +868,17 @@ object MacroCompiler extends App {
} }
def run(args: List[String]) { def run(args: List[String]) {
val (params, costParams, forcedMemories) = parseArgs(Map[MacroParam, String](), Map[String, String](), (Set.empty, Set.empty), args) val (params, costParams, forcedMemories) =
parseArgs(Map[MacroParam, String](), Map[String, String](), (Set.empty, Set.empty), args)
try { try {
val macros = params.get(MacrosFormat) match { val macros = params.get(MacrosFormat) match {
case Some("conf") => Utils.filterForSRAM(Utils.readConfFromPath(params.get(Macros))).get map (x => (new Macro(x)).blackbox) case Some("conf") =>
case _ => Utils.filterForSRAM(mdf.macrolib.Utils.readMDFFromPath(params.get(Macros))).get map (x => (new Macro(x)).blackbox) Utils.filterForSRAM(Utils.readConfFromPath(params.get(Macros))).get.map(x => (new Macro(x)).blackbox)
case _ =>
Utils
.filterForSRAM(mdf.macrolib.Utils.readMDFFromPath(params.get(Macros)))
.get
.map(x => (new Macro(x)).blackbox)
} }
if (macros.nonEmpty) { if (macros.nonEmpty) {
@@ -821,24 +886,28 @@ object MacroCompiler extends App {
// determined as the firrtl "top-level module". // determined as the firrtl "top-level module".
val circuit = Circuit(NoInfo, macros, macros.last.name) val circuit = Circuit(NoInfo, macros, macros.last.name)
val annotations = AnnotationSeq( val annotations = AnnotationSeq(
Seq(MacroCompilerAnnotation( Seq(
MacroCompilerAnnotation(
circuit.main, circuit.main,
MacroCompilerAnnotation.Params( MacroCompilerAnnotation.Params(
params.get(Macros).get, params.get(MacrosFormat), params.get(Library), params.get(Macros).get,
params.get(MacrosFormat),
params.get(Library),
params.get(HammerIR), params.get(HammerIR),
CostMetric.getCostMetric(params.getOrElse(CostFunc, "default"), costParams), CostMetric.getCostMetric(params.getOrElse(CostFunc, "default"), costParams),
MacroCompilerAnnotation.stringToCompilerMode(params.getOrElse(Mode, "default")), MacroCompilerAnnotation.stringToCompilerMode(params.getOrElse(Mode, "default")),
params.contains(UseCompiler), params.contains(UseCompiler),
forceCompile = forcedMemories._1, forceSynflops = forcedMemories._2 forceCompile = forcedMemories._1,
forceSynflops = forcedMemories._2
)
)
) )
))
) )
// The actual MacroCompilerTransform basically just generates an input circuit // The actual MacroCompilerTransform basically just generates an input circuit
val macroCompilerInput = CircuitState(circuit, MidForm, annotations) val macroCompilerInput = CircuitState(circuit, MidForm, annotations)
val macroCompiled = (new MacroCompilerTransform).execute(macroCompilerInput) val macroCompiled = (new MacroCompilerTransform).execute(macroCompilerInput)
// Since the MacroCompiler defines its own CLI, reconcile this with FIRRTL options // Since the MacroCompiler defines its own CLI, reconcile this with FIRRTL options
val firOptions = new ExecutionOptionsManager("macrocompiler") with HasFirrtlOptions { val firOptions = new ExecutionOptionsManager("macrocompiler") with HasFirrtlOptions {
firrtlOptions = FirrtlExecutionOptions( firrtlOptions = FirrtlExecutionOptions(
@@ -864,7 +933,7 @@ object MacroCompiler extends App {
} }
} else { } else {
// Warn user // Warn user
System.err println "WARNING: Empty *.mems.conf file. No memories generated." System.err.println("WARNING: Empty *.mems.conf file. No memories generated.")
// Emit empty verilog file if no macros found // Emit empty verilog file if no macros found
params.get(Verilog) match { params.get(Verilog) match {

View File

@@ -10,8 +10,9 @@ import firrtl.passes.MemPortUtils.memPortField
class SynFlopsPass(synflops: Boolean, libs: Seq[Macro]) extends firrtl.passes.Pass { class SynFlopsPass(synflops: Boolean, libs: Seq[Macro]) extends firrtl.passes.Pass {
val extraMods = scala.collection.mutable.ArrayBuffer.empty[Module] val extraMods = scala.collection.mutable.ArrayBuffer.empty[Module]
lazy val libMods = (libs map { lib => lib.src.name -> { lazy val libMods = (libs.map { lib =>
val (dataType, dataWidth) = (lib.src.ports foldLeft (None: Option[BigInt]))((res, port) => lib.src.name -> {
val (dataType, dataWidth) = (lib.src.ports.foldLeft(None: Option[BigInt]))((res, port) =>
(res, port.maskPort) match { (res, port.maskPort) match {
case (_, None) => case (_, None) =>
res res
@@ -31,10 +32,20 @@ class SynFlopsPass(synflops: Boolean, libs: Seq[Macro]) extends firrtl.passes.Pa
// Change macro to be mapped onto to look like the below mem // Change macro to be mapped onto to look like the below mem
// by changing its depth, and width // by changing its depth, and width
val lib_macro = new Macro(lib.src.copy(name="split_"+lib.src.name, val lib_macro = new Macro(
depth = maxDepth, width = dataWidth, ports = lib.src.ports.map(p => lib.src.copy(
p.copy(width = p.width.map(_ => dataWidth), depth = p.depth.map(_ => maxDepth), name = "split_" + lib.src.name,
maskGran = p.maskGran.map(_ => dataWidth))))) depth = maxDepth,
width = dataWidth,
ports = lib.src.ports.map(p =>
p.copy(
width = p.width.map(_ => dataWidth),
depth = p.depth.map(_ => maxDepth),
maskGran = p.maskGran.map(_ => dataWidth)
)
)
)
)
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 (real_mod, real_macro) = mod_macro.get
@@ -45,18 +56,17 @@ class SynFlopsPass(synflops: Boolean, libs: Seq[Macro]) extends firrtl.passes.Pa
maxDepth, maxDepth,
1, // writeLatency 1, // writeLatency
1, // readLatency. This is possible because of VerilogMemDelays 1, // readLatency. This is possible because of VerilogMemDelays
real_macro.readers.indices map (i => s"R_$i"), real_macro.readers.indices.map(i => s"R_$i"),
real_macro.writers.indices map (i => s"W_$i"), real_macro.writers.indices.map(i => s"W_$i"),
real_macro.readwriters.indices map (i => s"RW_$i") real_macro.readwriters.indices.map(i => s"RW_$i")
) )
val readConnects = real_macro.readers.zipWithIndex flatMap { case (r, i) => val readConnects = real_macro.readers.zipWithIndex.flatMap { case (r, i) =>
val clock = portToExpression(r.src.clock.get) val clock = portToExpression(r.src.clock.get)
val address = portToExpression(r.src.address) val address = portToExpression(r.src.address)
val enable = (r.src chipEnable, r.src readEnable) match { val enable = (r.src chipEnable, r.src readEnable) match {
case (Some(en_port), Some(re_port)) => case (Some(en_port), Some(re_port)) =>
and(portToExpression(en_port), and(portToExpression(en_port), portToExpression(re_port))
portToExpression(re_port))
case (Some(en_port), None) => portToExpression(en_port) case (Some(en_port), None) => portToExpression(en_port)
case (None, Some(re_port)) => portToExpression(re_port) case (None, Some(re_port)) => portToExpression(re_port)
case (None, None) => one case (None, None) => one
@@ -71,13 +81,12 @@ class SynFlopsPass(synflops: Boolean, libs: Seq[Macro]) extends firrtl.passes.Pa
) )
} }
val writeConnects = real_macro.writers.zipWithIndex flatMap { case (w, i) => val writeConnects = real_macro.writers.zipWithIndex.flatMap { case (w, i) =>
val clock = portToExpression(w.src.clock.get) val clock = portToExpression(w.src.clock.get)
val address = portToExpression(w.src.address) val address = portToExpression(w.src.address)
val enable = (w.src.chipEnable, w.src.writeEnable) match { val enable = (w.src.chipEnable, w.src.writeEnable) match {
case (Some(en), Some(we)) => case (Some(en), Some(we)) =>
and(portToExpression(en), and(portToExpression(en), portToExpression(we))
portToExpression(we))
case (Some(en), None) => portToExpression(en) case (Some(en), None) => portToExpression(en)
case (None, Some(we)) => portToExpression(we) case (None, Some(we)) => portToExpression(we)
case (None, None) => zero // is it possible? case (None, None) => zero // is it possible?
@@ -97,7 +106,7 @@ class SynFlopsPass(synflops: Boolean, libs: Seq[Macro]) extends firrtl.passes.Pa
) )
} }
val readwriteConnects = real_macro.readwriters.zipWithIndex flatMap { case (rw, i) => val readwriteConnects = real_macro.readwriters.zipWithIndex.flatMap { case (rw, i) =>
val clock = portToExpression(rw.src.clock.get) val clock = portToExpression(rw.src.clock.get)
val address = portToExpression(rw.src.address) val address = portToExpression(rw.src.address)
val wmode = rw.src.writeEnable match { val wmode = rw.src.writeEnable match {
@@ -132,10 +141,11 @@ class SynFlopsPass(synflops: Boolean, libs: Seq[Macro]) extends firrtl.passes.Pa
extraMods.append(real_macro.module(Block(mem +: (readConnects ++ writeConnects ++ readwriteConnects)))) extraMods.append(real_macro.module(Block(mem +: (readConnects ++ writeConnects ++ readwriteConnects))))
real_mod real_mod
}}).toMap }
}).toMap
def run(c: Circuit): Circuit = { def run(c: Circuit): Circuit = {
if (!synflops) c 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)
} }
} }

View File

@@ -21,37 +21,46 @@ class FirrtlMacroPort(port: MacroPort) {
val isWriter = port.input.nonEmpty && port.output.isEmpty val isWriter = port.input.nonEmpty && port.output.isEmpty
val isReadWriter = port.input.nonEmpty && port.output.nonEmpty val isReadWriter = port.input.nonEmpty && port.output.nonEmpty
val addrType = UIntType(IntWidth(MacroCompilerMath.ceilLog2(port.depth.get) max 1)) val addrType = UIntType(IntWidth(MacroCompilerMath.ceilLog2(port.depth.get).max(1)))
val dataType = UIntType(IntWidth(port.width.get)) val dataType = UIntType(IntWidth(port.width.get))
val maskType = UIntType(IntWidth(port.width.get / port.effectiveMaskGran)) val maskType = UIntType(IntWidth(port.width.get / port.effectiveMaskGran))
// Bundle representing this macro port. // Bundle representing this macro port.
val tpe = BundleType(Seq( val tpe = BundleType(
Field(port.address.name, Flip, addrType)) ++ Seq(Field(port.address.name, Flip, addrType)) ++
(port.clock map (p => Field(p.name, Flip, ClockType))) ++ (port.clock.map(p => Field(p.name, Flip, ClockType))) ++
(port.input map (p => Field(p.name, Flip, dataType))) ++ (port.input.map(p => Field(p.name, Flip, dataType))) ++
(port.output map (p => Field(p.name, Default, dataType))) ++ (port.output.map(p => Field(p.name, Default, dataType))) ++
(port.chipEnable map (p => Field(p.name, Flip, BoolType))) ++ (port.chipEnable.map(p => Field(p.name, Flip, BoolType))) ++
(port.readEnable 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.writeEnable.map(p => Field(p.name, Flip, BoolType))) ++
(port.maskPort map (p => Field(p.name, Flip, maskType))) (port.maskPort.map(p => Field(p.name, Flip, maskType)))
)
val ports = tpe.fields.map(f =>
Port(
NoInfo,
f.name,
f.flip match {
case Default => Output
case Flip => Input
},
f.tpe
)
) )
val ports = tpe.fields map (f => Port(
NoInfo, f.name, f.flip match { case Default => Output case Flip => Input }, f.tpe))
} }
// Reads an SRAMMacro and generates firrtl blackboxes. // Reads an SRAMMacro and generates firrtl blackboxes.
class Macro(srcMacro: SRAMMacro) { class Macro(srcMacro: SRAMMacro) {
val src = srcMacro val src = srcMacro
val firrtlPorts = srcMacro.ports map { new FirrtlMacroPort(_) } val firrtlPorts = srcMacro.ports.map { new FirrtlMacroPort(_) }
val writers = firrtlPorts filter (p => p.isWriter) val writers = firrtlPorts.filter(p => p.isWriter)
val readers = firrtlPorts filter (p => p.isReader) val readers = firrtlPorts.filter(p => p.isReader)
val readwriters = firrtlPorts filter (p => p.isReadWriter) val readwriters = firrtlPorts.filter(p => p.isReadWriter)
val sortedPorts = writers ++ readers ++ readwriters val sortedPorts = writers ++ readers ++ readwriters
val extraPorts = srcMacro.extraPorts map { p => val extraPorts = srcMacro.extraPorts.map { p =>
assert(p.portType == Constant) // TODO: release it? assert(p.portType == Constant) // TODO: release it?
val name = p.name val name = p.name
val width = BigInt(p.width.toLong) val width = BigInt(p.width.toLong)
@@ -60,10 +69,10 @@ class Macro(srcMacro: SRAMMacro) {
} }
// Bundle representing this memory blackbox // Bundle representing this memory blackbox
val tpe = BundleType(firrtlPorts flatMap (_.tpe.fields)) val tpe = BundleType(firrtlPorts.flatMap(_.tpe.fields))
private val modPorts = (firrtlPorts flatMap (_.ports)) ++ private val modPorts = (firrtlPorts.flatMap(_.ports)) ++
(extraPorts map { case (name, value) => Port(NoInfo, name, Input, value.tpe) }) (extraPorts.map { case (name, value) => Port(NoInfo, name, Input, value.tpe) })
val blackbox = ExtModule(NoInfo, srcMacro.name, modPorts, srcMacro.name, Nil) val blackbox = ExtModule(NoInfo, srcMacro.name, modPorts, srcMacro.name, Nil)
def module(body: Statement) = Module(NoInfo, srcMacro.name, modPorts, body) def module(body: Statement) = Module(NoInfo, srcMacro.name, modPorts, body)
} }
@@ -71,7 +80,8 @@ class Macro(srcMacro: SRAMMacro) {
object Utils { object Utils {
def filterForSRAM(s: Option[Seq[mdf.macrolib.Macro]]): Option[Seq[mdf.macrolib.SRAMMacro]] = { def filterForSRAM(s: Option[Seq[mdf.macrolib.Macro]]): Option[Seq[mdf.macrolib.SRAMMacro]] = {
s match { s match {
case Some(l:Seq[mdf.macrolib.Macro]) => Some(l filter { _.isInstanceOf[mdf.macrolib.SRAMMacro] } map { m => m.asInstanceOf[mdf.macrolib.SRAMMacro] }) case Some(l: Seq[mdf.macrolib.Macro]) =>
Some(l.filter { _.isInstanceOf[mdf.macrolib.SRAMMacro] }.map { m => m.asInstanceOf[mdf.macrolib.SRAMMacro] })
case _ => None case _ => None
} }
} }
@@ -81,8 +91,14 @@ object Utils {
} }
def readConfFromString(str: String): Seq[mdf.macrolib.Macro] = { def readConfFromString(str: String): Seq[mdf.macrolib.Macro] = {
MemConf.fromString(str).map { m: MemConf => MemConf.fromString(str).map { m: MemConf =>
val ports = m.ports.map { case (port, num) => Seq.fill(num)(port) } reduce (_ ++ _) val ports = m.ports.map { case (port, num) => Seq.fill(num)(port) }.reduce(_ ++ _)
SRAMMacro(m.name, m.width, m.depth, Utils.portSpecToFamily(ports), Utils.portSpecToMacroPort(m.width, m.depth, m.maskGranularity, ports)) SRAMMacro(
m.name,
m.width,
m.depth,
Utils.portSpecToFamily(ports),
Utils.portSpecToMacroPort(m.width, m.depth, m.maskGranularity, ports)
)
} }
} }
def portSpecToFamily(ports: Seq[MemPort]): String = { def portSpecToFamily(ports: Seq[MemPort]): String = {
@@ -99,56 +115,66 @@ object Utils {
var numR = 0 var numR = 0
var numW = 0 var numW = 0
var numRW = 0 var numRW = 0
ports.map { _ match { ports.map {
_ match {
case ReadPort => { case ReadPort => {
val portName = s"R${numR}" val portName = s"R${numR}"
numR += 1 numR += 1
MacroPort( MacroPort(
width=Some(width), depth=Some(depth), width = Some(width),
depth = Some(depth),
address = PolarizedPort(s"${portName}_addr", ActiveHigh), address = PolarizedPort(s"${portName}_addr", ActiveHigh),
clock = Some(PolarizedPort(s"${portName}_clk", PositiveEdge)), clock = Some(PolarizedPort(s"${portName}_clk", PositiveEdge)),
readEnable = Some(PolarizedPort(s"${portName}_en", ActiveHigh)), readEnable = Some(PolarizedPort(s"${portName}_en", ActiveHigh)),
output = Some(PolarizedPort(s"${portName}_data", ActiveHigh)) output = Some(PolarizedPort(s"${portName}_data", ActiveHigh))
) } )
}
case WritePort => { case WritePort => {
val portName = s"W${numW}" val portName = s"W${numW}"
numW += 1 numW += 1
MacroPort( MacroPort(
width=Some(width), depth=Some(depth), width = Some(width),
depth = Some(depth),
address = PolarizedPort(s"${portName}_addr", ActiveHigh), address = PolarizedPort(s"${portName}_addr", ActiveHigh),
clock = Some(PolarizedPort(s"${portName}_clk", PositiveEdge)), clock = Some(PolarizedPort(s"${portName}_clk", PositiveEdge)),
writeEnable = Some(PolarizedPort(s"${portName}_en", ActiveHigh)), writeEnable = Some(PolarizedPort(s"${portName}_en", ActiveHigh)),
input = Some(PolarizedPort(s"${portName}_data", ActiveHigh)) input = Some(PolarizedPort(s"${portName}_data", ActiveHigh))
) } )
}
case MaskedWritePort => { case MaskedWritePort => {
val portName = s"W${numW}" val portName = s"W${numW}"
numW += 1 numW += 1
MacroPort( MacroPort(
width=Some(width), depth=Some(depth), width = Some(width),
depth = Some(depth),
address = PolarizedPort(s"${portName}_addr", ActiveHigh), address = PolarizedPort(s"${portName}_addr", ActiveHigh),
clock = Some(PolarizedPort(s"${portName}_clk", PositiveEdge)), clock = Some(PolarizedPort(s"${portName}_clk", PositiveEdge)),
writeEnable = Some(PolarizedPort(s"${portName}_en", ActiveHigh)), writeEnable = Some(PolarizedPort(s"${portName}_en", ActiveHigh)),
maskPort = Some(PolarizedPort(s"${portName}_mask", ActiveHigh)), maskPort = Some(PolarizedPort(s"${portName}_mask", ActiveHigh)),
maskGran = maskGran, maskGran = maskGran,
input = Some(PolarizedPort(s"${portName}_data", ActiveHigh)) input = Some(PolarizedPort(s"${portName}_data", ActiveHigh))
) } )
}
case ReadWritePort => { case ReadWritePort => {
val portName = s"RW${numRW}" val portName = s"RW${numRW}"
numRW += 1 numRW += 1
MacroPort( MacroPort(
width=Some(width), depth=Some(depth), width = Some(width),
depth = Some(depth),
address = PolarizedPort(s"${portName}_addr", ActiveHigh), address = PolarizedPort(s"${portName}_addr", ActiveHigh),
clock = Some(PolarizedPort(s"${portName}_clk", PositiveEdge)), clock = Some(PolarizedPort(s"${portName}_clk", PositiveEdge)),
chipEnable = Some(PolarizedPort(s"${portName}_en", ActiveHigh)), chipEnable = Some(PolarizedPort(s"${portName}_en", ActiveHigh)),
writeEnable = Some(PolarizedPort(s"${portName}_wmode", ActiveHigh)), writeEnable = Some(PolarizedPort(s"${portName}_wmode", ActiveHigh)),
input = Some(PolarizedPort(s"${portName}_wdata", ActiveHigh)), input = Some(PolarizedPort(s"${portName}_wdata", ActiveHigh)),
output = Some(PolarizedPort(s"${portName}_rdata", ActiveHigh)) output = Some(PolarizedPort(s"${portName}_rdata", ActiveHigh))
) } )
}
case MaskedReadWritePort => { case MaskedReadWritePort => {
val portName = s"RW${numRW}" val portName = s"RW${numRW}"
numRW += 1 numRW += 1
MacroPort( MacroPort(
width=Some(width), depth=Some(depth), width = Some(width),
depth = Some(depth),
address = PolarizedPort(s"${portName}_addr", ActiveHigh), address = PolarizedPort(s"${portName}_addr", ActiveHigh),
clock = Some(PolarizedPort(s"${portName}_clk", PositiveEdge)), clock = Some(PolarizedPort(s"${portName}_clk", PositiveEdge)),
chipEnable = Some(PolarizedPort(s"${portName}_en", ActiveHigh)), chipEnable = Some(PolarizedPort(s"${portName}_en", ActiveHigh)),
@@ -157,24 +183,48 @@ object Utils {
maskGran = maskGran, maskGran = maskGran,
input = Some(PolarizedPort(s"${portName}_wdata", ActiveHigh)), input = Some(PolarizedPort(s"${portName}_wdata", ActiveHigh)),
output = Some(PolarizedPort(s"${portName}_rdata", ActiveHigh)) output = Some(PolarizedPort(s"${portName}_rdata", ActiveHigh))
) } )
}} }
}
}
} }
def findSRAMCompiler(s: Option[Seq[mdf.macrolib.Macro]]): Option[mdf.macrolib.SRAMCompiler] = { def findSRAMCompiler(s: Option[Seq[mdf.macrolib.Macro]]): Option[mdf.macrolib.SRAMCompiler] = {
s match { s match {
case Some(l: Seq[mdf.macrolib.Macro]) => case Some(l: Seq[mdf.macrolib.Macro]) =>
l collectFirst { l.collectFirst { case x: mdf.macrolib.SRAMCompiler =>
case x: mdf.macrolib.SRAMCompiler => x x
} }
case _ => None case _ => None
} }
} }
def buildSRAMMacros(s: mdf.macrolib.SRAMCompiler): Seq[mdf.macrolib.SRAMMacro] = { def buildSRAMMacros(s: mdf.macrolib.SRAMCompiler): Seq[mdf.macrolib.SRAMMacro] = {
for (g <- s.groups; d <- g.depth; w <- g.width; vt <- g.vt) for {
yield mdf.macrolib.SRAMMacro(makeName(g, d, w, vt), w, d, g.family, g.ports.map(_.copy(width=Some(w), depth=Some(d))), vt, g.mux, g.extraPorts) 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))),
vt,
g.mux,
g.extraPorts
)
} }
def buildSRAMMacro(g: mdf.macrolib.SRAMGroup, d: Int, w: Int, vt: String): mdf.macrolib.SRAMMacro = { def buildSRAMMacro(g: mdf.macrolib.SRAMGroup, d: Int, w: Int, vt: String): mdf.macrolib.SRAMMacro = {
return mdf.macrolib.SRAMMacro(makeName(g, d, w, vt), w, d, g.family, g.ports.map(_.copy(width=Some(w), depth=Some(d))), vt, g.mux, g.extraPorts) return mdf.macrolib.SRAMMacro(
makeName(g, d, w, vt),
w,
d,
g.family,
g.ports.map(_.copy(width = Some(w), depth = Some(d))),
vt,
g.mux,
g.extraPorts
)
} }
def makeName(g: mdf.macrolib.SRAMGroup, depth: Int, width: Int, vt: String): String = { def makeName(g: mdf.macrolib.SRAMGroup, depth: Int, width: Int, vt: String): String = {
g.name.foldLeft("") { (builder, next) => g.name.foldLeft("") { (builder, next) =>

View File

@@ -6,7 +6,8 @@
"depth": "512", "depth": "512",
"mux": 4, "mux": 4,
"family": "1rw", "family": "1rw",
"ports" : [ { "ports": [
{
"address port name": "addr", "address port name": "addr",
"address port polarity": "active high", "address port polarity": "active high",
"clock port name": "clk", "clock port name": "clk",
@@ -22,6 +23,7 @@
"mask port name": "mport", "mask port name": "mport",
"mask port polarity": "active low", "mask port polarity": "active low",
"mask granularity": 1 "mask granularity": 1
} ] }
]
} }
] ]

View File

@@ -6,7 +6,8 @@
"depth": "4096", "depth": "4096",
"mux": 4, "mux": 4,
"family": "1rw", "family": "1rw",
"ports" : [ { "ports": [
{
"address port name": "addr", "address port name": "addr",
"address port polarity": "active high", "address port polarity": "active high",
"clock port name": "clk", "clock port name": "clk",
@@ -19,6 +20,7 @@
"output port polarity": "active high", "output port polarity": "active high",
"input port name": "datain", "input port name": "datain",
"input port polarity": "active high" "input port polarity": "active high"
} ] }
]
} }
] ]

View File

@@ -4,8 +4,7 @@ import mdf.macrolib._
/** Tests to check that the cost function mechanism is working properly. */ /** Tests to check that the cost function mechanism is working properly. */
/** /** A test metric that simply favours memories with smaller widths, to test that
* A test metric that simply favours memories with smaller widths, to test that
* the metric is chosen properly. * the metric is chosen properly.
*/ */
object TestMinWidthMetric extends CostMetric with CostMetricCompanion { object TestMinWidthMetric extends CostMetric with CostMetricCompanion {

View File

@@ -39,7 +39,10 @@ abstract class MacroCompilerSpec extends org.scalatest.FlatSpec with org.scalate
private def args(mem: String, lib: Option[String], v: String, synflops: Boolean, useCompiler: Boolean) = private def args(mem: String, lib: Option[String], v: String, synflops: Boolean, useCompiler: Boolean) =
List("-m", mem.toString, "-v", v) ++ List("-m", mem.toString, "-v", v) ++
(lib match { case None => Nil case Some(l) => List("-l", l.toString) }) ++ (lib match {
case None => Nil
case Some(l) => List("-l", l.toString)
}) ++
costMetricCmdLine ++ costMetricCmdLine ++
(if (synflops) List("--mode", "synflops") else Nil) ++ (if (synflops) List("--mode", "synflops") else Nil) ++
(if (useCompiler) List("--use-compiler") else Nil) (if (useCompiler) List("--use-compiler") else Nil)
@@ -68,7 +71,14 @@ abstract class MacroCompilerSpec extends org.scalatest.FlatSpec with org.scalate
} }
// Convenience function for running both compile, execute, and test at once. // Convenience function for running both compile, execute, and test at once.
def compileExecuteAndTest(mem: String, lib: Option[String], v: String, output: String, synflops: Boolean = false, useCompiler: Boolean = false): Unit = { def compileExecuteAndTest(
mem: String,
lib: Option[String],
v: String,
output: String,
synflops: Boolean = false,
useCompiler: Boolean = false
): Unit = {
compile(mem, lib, v, synflops, useCompiler) compile(mem, lib, v, synflops, useCompiler)
val result = execute(mem, lib, synflops, useCompiler) val result = execute(mem, lib, synflops, useCompiler)
test(result, output) test(result, output)
@@ -76,38 +86,48 @@ abstract class MacroCompilerSpec extends org.scalatest.FlatSpec with org.scalate
// Compare FIRRTL outputs after reparsing output with ScalaTest ("should be"). // Compare FIRRTL outputs after reparsing output with ScalaTest ("should be").
def test(result: Circuit, output: String): Unit = { def test(result: Circuit, output: String): Unit = {
val gold = RemoveEmpty run parse(output) 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 // Execute the macro compiler and returns a Circuit containing the output of
// the memory compiler. // the memory compiler.
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): Circuit =
execute(memFile, libFile, synflops, false)
def execute(memFile: Option[String], libFile: Option[String], synflops: Boolean, useCompiler: Boolean): Circuit = { def execute(memFile: Option[String], libFile: Option[String], synflops: Boolean, useCompiler: Boolean): Circuit = {
var mem_full = concat(memPrefix, memFile) var mem_full = concat(memPrefix, memFile)
var lib_full = concat(libPrefix, libFile) var lib_full = concat(libPrefix, libFile)
require(memFile.isDefined) require(memFile.isDefined)
val mems: Seq[Macro] = Utils.filterForSRAM(mdf.macrolib.Utils.readMDFFromPath(mem_full)).get map (new Macro(_)) val mems: Seq[Macro] = Utils.filterForSRAM(mdf.macrolib.Utils.readMDFFromPath(mem_full)).get.map(new Macro(_))
val libs: Option[Seq[Macro]] = if (useCompiler) { val libs: Option[Seq[Macro]] = if (useCompiler) {
Utils.findSRAMCompiler(mdf.macrolib.Utils.readMDFFromPath(lib_full)).map{x => Utils.buildSRAMMacros(x).map(new Macro(_)) } Utils.findSRAMCompiler(mdf.macrolib.Utils.readMDFFromPath(lib_full)).map { x =>
Utils.buildSRAMMacros(x).map(new Macro(_))
}
} else { } else {
Utils.filterForSRAM(mdf.macrolib.Utils.readMDFFromPath(lib_full)) match { Utils.filterForSRAM(mdf.macrolib.Utils.readMDFFromPath(lib_full)) match {
case Some(x) => Some(x map (new Macro(_))) case Some(x) => Some(x.map(new Macro(_)))
case None => None case None => None
} }
} }
val macros = mems map (_.blackbox) val macros = mems.map(_.blackbox)
val circuit = Circuit(NoInfo, macros, macros.last.name) val circuit = Circuit(NoInfo, macros, macros.last.name)
val passes = Seq( val passes = Seq(
new MacroCompilerPass(Some(mems), libs, None, None, getCostMetric, if (synflops) MacroCompilerAnnotation.Synflops else MacroCompilerAnnotation.Default), new MacroCompilerPass(
new SynFlopsPass(synflops, libs getOrElse mems), Some(mems),
RemoveEmpty) libs,
val result: Circuit = (passes foldLeft circuit)((c, pass) => pass run c) None,
None,
getCostMetric,
if (synflops) MacroCompilerAnnotation.Synflops else MacroCompilerAnnotation.Default
),
new SynFlopsPass(synflops, libs.getOrElse(mems)),
RemoveEmpty
)
val result: Circuit = (passes.foldLeft(circuit))((c, pass) => pass.run(c))
result result
} }
// Helper method to deal with String + Option[String] // Helper method to deal with String + Option[String]
private def concat(a: String, b: String): String = { a + "/" + b } private def concat(a: String, b: String): String = { a + "/" + b }
private def concat(a: String, b: Option[String]): Option[String] = { private def concat(a: String, b: Option[String]): Option[String] = {
@@ -126,7 +146,6 @@ trait HasSRAMGenerator {
implicit def Int2SomeInt(i: Int): Option[Int] = Some(i) implicit def Int2SomeInt(i: Int): Option[Int] = Some(i)
implicit def BigInt2SomeBigInt(i: BigInt): Option[BigInt] = Some(i) implicit def BigInt2SomeBigInt(i: BigInt): Option[BigInt] = Some(i)
// Generate a standard (read/write/combo) port for testing. // Generate a standard (read/write/combo) port for testing.
// Helper methods for optional width argument // Helper methods for optional width argument
def generateTestPort( def generateTestPort(
@@ -144,44 +163,70 @@ trait HasSRAMGenerator {
MacroPort( MacroPort(
address = PolarizedPort(name = realPrefix + "addr", polarity = ActiveHigh), address = PolarizedPort(name = realPrefix + "addr", polarity = ActiveHigh),
clock = Some(PolarizedPort(name = realPrefix + "clk", polarity = PositiveEdge)), clock = Some(PolarizedPort(name = realPrefix + "clk", polarity = PositiveEdge)),
readEnable = if (readEnable) Some(PolarizedPort(name = realPrefix + "read_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, 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, output = if (read) Some(PolarizedPort(name = realPrefix + "dout", polarity = ActiveHigh)) else None,
input = if (write) Some(PolarizedPort(name = realPrefix + "din", polarity = ActiveHigh)) else None, input = if (write) Some(PolarizedPort(name = realPrefix + "din", polarity = ActiveHigh)) else None,
maskPort = maskGran match { maskPort = maskGran match {
case Some(x: Int) => Some(PolarizedPort(name = realPrefix + "mask", polarity = ActiveHigh)) case Some(x: Int) => Some(PolarizedPort(name = realPrefix + "mask", polarity = ActiveHigh))
case _ => None case _ => None
}, },
maskGran = maskGran, maskGran = maskGran,
width = width,
width = width, depth = depth // These numbers don't matter here. depth = depth // These numbers don't matter here.
) )
} }
// Generate a read port for testing. // Generate a read port for testing.
def generateReadPort(prefix: String, width: Option[Int], depth: Option[BigInt], readEnable: Boolean = false): MacroPort = { def generateReadPort(
prefix: String,
width: Option[Int],
depth: Option[BigInt],
readEnable: Boolean = false
): MacroPort = {
generateTestPort(prefix, width, depth, write = false, read = true, readEnable = readEnable) generateTestPort(prefix, width, depth, write = false, read = true, readEnable = readEnable)
} }
// Generate a write port for testing. // Generate a write port for testing.
def generateWritePort(prefix: String, width: Option[Int], depth: Option[BigInt], maskGran: Option[Int] = None, writeEnable: Boolean = true): MacroPort = { def generateWritePort(
prefix: String,
width: Option[Int],
depth: Option[BigInt],
maskGran: Option[Int] = None,
writeEnable: Boolean = true
): MacroPort = {
generateTestPort(prefix, width, depth, maskGran = maskGran, write = true, read = false, writeEnable = writeEnable) generateTestPort(prefix, width, depth, maskGran = maskGran, write = true, read = false, writeEnable = writeEnable)
} }
// Generate a simple read-write port for testing. // Generate a simple read-write port for testing.
def generateReadWritePort(prefix: String, width: Option[Int], depth: Option[BigInt], maskGran: Option[Int] = None): MacroPort = { def generateReadWritePort(
prefix: String,
width: Option[Int],
depth: Option[BigInt],
maskGran: Option[Int] = None
): MacroPort = {
generateTestPort( generateTestPort(
prefix, width, depth, maskGran = maskGran, prefix,
write = true, writeEnable = true, width,
read = true, readEnable = false depth,
maskGran = maskGran,
write = true,
writeEnable = true,
read = true,
readEnable = false
) )
} }
// Generate a "simple" SRAM (active high/positive edge, 1 read-write port). // Generate a "simple" SRAM (active high/positive edge, 1 read-write port).
def generateSRAM(name: String, prefix: String, width: Int, depth: BigInt, maskGran: Option[Int] = None, extraPorts: Seq[MacroExtraPort] = List()): SRAMMacro = { def generateSRAM(
name: String,
prefix: String,
width: Int,
depth: BigInt,
maskGran: Option[Int] = None,
extraPorts: Seq[MacroExtraPort] = List()
): SRAMMacro = {
SRAMMacro( SRAMMacro(
name = name, name = name,
width = width, width = width,
@@ -193,17 +238,35 @@ trait HasSRAMGenerator {
} }
// Generate a "simple" SRAM group (active high/positive edge, 1 read-write port). // 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 = { def generateSimpleSRAMGroup(
SRAMGroup(Seq("mygroup_", "width", "x", "depth", "_", "VT"), "1rw", Seq("svt", "lvt", "ulvt"), mux, depth, width, Seq(generateReadWritePort(prefix, None, None, maskGran))) 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': 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} // '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 = { def generateSRAMCompiler(name: String, prefix: String): mdf.macrolib.SRAMCompiler = {
SRAMCompiler(name, Seq( SRAMCompiler(
name,
Seq(
generateSimpleSRAMGroup(prefix, 2, Range(16, 512, 8), Range(8, 288, 2)), generateSimpleSRAMGroup(prefix, 2, Range(16, 512, 8), Range(8, 288, 2)),
generateSimpleSRAMGroup(prefix, 4, Range(32, 1024, 16), Range(4, 144, 1)) generateSimpleSRAMGroup(prefix, 4, Range(32, 1024, 16), Range(4, 144, 1))
)) )
)
} }
} }
@@ -288,8 +351,7 @@ trait HasSimpleTestGenerator {
lazy val lastWidthBits = if (memWidth % usableLibWidth == 0) usableLibWidth else (memWidth % usableLibWidth) lazy val lastWidthBits = if (memWidth % usableLibWidth == 0) usableLibWidth else (memWidth % usableLibWidth)
lazy val selectBits = mem_addr_width - lib_addr_width lazy val selectBits = mem_addr_width - lib_addr_width
/** /** Convenience function to generate a mask statement.
* Convenience function to generate a mask statement.
* @param widthInst Width instance (mem_0_x) * @param widthInst Width instance (mem_0_x)
* @param depthInst Depth instance (mem_x_0) * @param depthInst Depth instance (mem_x_0)
*/ */
@@ -312,7 +374,7 @@ trait HasSimpleTestGenerator {
// calculateMaskBit({0, 1}) = 0 and calculateMaskBit({1, 2}) = 1 // calculateMaskBit({0, 1}) = 0 and calculateMaskBit({1, 2}) = 1
def calculateMaskBit(bit: Int): Int = bit / memMaskGran.getOrElse(memWidth) 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 (x * libMaskGran.get > myMemWidth) {
// If we have extra mask bits leftover after the effective width, // If we have extra mask bits leftover after the effective width,
// disable those bits. // disable those bits.
@@ -340,7 +402,17 @@ trait HasSimpleTestGenerator {
* @param mask Mask granularity (# bits) of the port or None. * @param mask Mask granularity (# bits) of the port or None.
* @param extraPorts Extra ports (name, # bits) * @param extraPorts Extra ports (name, # bits)
*/ */
def generatePort(prefix: String, addrWidth: Int, width: Int, write: Boolean, writeEnable: Boolean, read: Boolean, readEnable: Boolean, mask: Option[Int], extraPorts: Seq[(String, Int)] = Seq()): String = { def generatePort(
prefix: String,
addrWidth: Int,
width: Int,
write: Boolean,
writeEnable: Boolean,
read: Boolean,
readEnable: Boolean,
mask: Option[Int],
extraPorts: Seq[(String, Int)] = Seq()
): String = {
val realPrefix = if (prefix == "") "" else prefix + "_" val realPrefix = if (prefix == "") "" else prefix + "_"
val readStr = if (read) s"output ${realPrefix}dout : UInt<$width>" else "" val readStr = if (read) s"output ${realPrefix}dout : UInt<$width>" else ""
@@ -364,32 +436,58 @@ $extraPortsStr
""" """
} }
/** /** Helper function to generate a RW footer port.
* Helper function to generate a RW footer port.
* *
* @param prefix Memory port prefix (e.g. "x" for ports like "x_clk") * @param prefix Memory port prefix (e.g. "x" for ports like "x_clk")
* @param readEnable Has a read enable port? * @param readEnable Has a read enable port?
* @param mask Mask granularity (# bits) of the port or None. * @param mask Mask granularity (# bits) of the port or None.
* @param extraPorts Extra ports (name, # bits) * @param extraPorts Extra ports (name, # bits)
*/ */
def generateReadWriteFooterPort(prefix: String, readEnable: Boolean, mask: Option[Int], extraPorts: Seq[(String, Int)] = Seq()): String = { def generateReadWriteFooterPort(
generatePort(prefix, lib_addr_width, libWidth, prefix: String,
write = true, writeEnable = true, read = true, readEnable = readEnable, mask = mask, extraPorts = extraPorts) readEnable: Boolean,
mask: Option[Int],
extraPorts: Seq[(String, Int)] = Seq()
): String = {
generatePort(
prefix,
lib_addr_width,
libWidth,
write = true,
writeEnable = true,
read = true,
readEnable = readEnable,
mask = mask,
extraPorts = extraPorts
)
} }
/** Helper function to generate a RW header port. /** Helper function to generate a RW header port.
* @param prefix Memory port prefix (e.g. "x" for ports like "x_clk") * @param prefix Memory port prefix (e.g. "x" for ports like "x_clk")
* @param readEnable Has a read enable port? * @param readEnable Has a read enable port?
* @param mask Mask granularity (# bits) of the port or None. */ * @param mask Mask granularity (# bits) of the port or None.
*/
def generateReadWriteHeaderPort(prefix: String, readEnable: Boolean, mask: Option[Int]): String = { def generateReadWriteHeaderPort(prefix: String, readEnable: Boolean, mask: Option[Int]): String = {
generatePort(prefix, mem_addr_width, memWidth, generatePort(
write=true, writeEnable=true, read=true, readEnable=readEnable, mask) prefix,
mem_addr_width,
memWidth,
write = true,
writeEnable = true,
read = true,
readEnable = readEnable,
mask
)
} }
// Generate the header memory ports. // Generate the header memory ports.
def generateHeaderPorts(): String = { def generateHeaderPorts(): String = {
require(memSRAM.ports.size == 1, "Header generator only supports single RW port mem") require(memSRAM.ports.size == 1, "Header generator only supports single RW port mem")
generateReadWriteHeaderPort(memPortPrefix, memSRAM.ports(0).readEnable.isDefined, if (memHasMask) Some(memMaskBits) else None) generateReadWriteHeaderPort(
memPortPrefix,
memSRAM.ports(0).readEnable.isDefined,
if (memHasMask) Some(memMaskBits) else None
)
} }
// Generate the header (contains the circuit statement and the target memory // Generate the header (contains the circuit statement and the target memory
@@ -405,8 +503,12 @@ ${generateHeaderPorts}
// Generate the target memory ports. // Generate the target memory ports.
def generateFooterPorts(): String = { def generateFooterPorts(): String = {
require(libSRAM.ports.size == 1, "Footer generator only supports single RW port mem") require(libSRAM.ports.size == 1, "Footer generator only supports single RW port mem")
generateReadWriteFooterPort(libPortPrefix, libSRAM.ports(0).readEnable.isDefined, generateReadWriteFooterPort(
if (libHasMask) Some(libMaskBits) else None, extraPorts.map(p => (p.name, p.width))) libPortPrefix,
libSRAM.ports(0).readEnable.isDefined,
if (libHasMask) Some(libMaskBits) else None,
extraPorts.map(p => (p.name, p.width))
)
} }
// Generate the footer (contains the target memory extmodule declaration by default). // Generate the footer (contains the target memory extmodule declaration by default).
@@ -450,4 +552,3 @@ trait HasNoLibTestGenerator extends HasSimpleTestGenerator {
// If there is no lib, don't generate a body. // If there is no lib, don't generate a body.
override def generateBody = "" override def generateBody = ""
} }

View File

@@ -9,9 +9,7 @@ trait MasksTestSettings {
} }
// Try all four different kinds of mask config: // Try all four different kinds of mask config:
/** /** Non-masked mem Masked mem
*
* Non-masked mem Masked mem
* --------------------------------- * ---------------------------------
* Non-masked lib | | | * Non-masked lib | | |
* --------------------------------- * ---------------------------------
@@ -19,7 +17,10 @@ trait MasksTestSettings {
* --------------------------------- * ---------------------------------
*/ */
class Masks_FourTypes_NonMaskedMem_NonMaskedLib extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator { class Masks_FourTypes_NonMaskedMem_NonMaskedLib
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024) override lazy val depth = BigInt(1024)
override lazy val memWidth = 32 override lazy val memWidth = 32
override lazy val memMaskGran = None override lazy val memMaskGran = None
@@ -29,7 +30,10 @@ class Masks_FourTypes_NonMaskedMem_NonMaskedLib extends MacroCompilerSpec with H
compileExecuteAndTest(mem, lib, v, output) compileExecuteAndTest(mem, lib, v, output)
} }
class Masks_FourTypes_NonMaskedMem_MaskedLib extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator { class Masks_FourTypes_NonMaskedMem_MaskedLib
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024) override lazy val depth = BigInt(1024)
override lazy val memWidth = 32 override lazy val memWidth = 32
override lazy val memMaskGran = None override lazy val memMaskGran = None
@@ -39,7 +43,10 @@ class Masks_FourTypes_NonMaskedMem_MaskedLib extends MacroCompilerSpec with HasS
compileExecuteAndTest(mem, lib, v, output) compileExecuteAndTest(mem, lib, v, output)
} }
class Masks_FourTypes_MaskedMem_NonMaskedLib extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator { class Masks_FourTypes_MaskedMem_NonMaskedLib
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024) override lazy val depth = BigInt(1024)
override lazy val memWidth = 32 override lazy val memWidth = 32
override lazy val memMaskGran = Some(8) override lazy val memMaskGran = Some(8)
@@ -49,7 +56,10 @@ class Masks_FourTypes_MaskedMem_NonMaskedLib extends MacroCompilerSpec with HasS
compileExecuteAndTest(mem, lib, v, output) compileExecuteAndTest(mem, lib, v, output)
} }
class Masks_FourTypes_MaskedMem_NonMaskedLib_SmallerMaskGran extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator { class Masks_FourTypes_MaskedMem_NonMaskedLib_SmallerMaskGran
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024) override lazy val depth = BigInt(1024)
override lazy val memWidth = 32 override lazy val memWidth = 32
override lazy val memMaskGran = Some(4) override lazy val memMaskGran = Some(4)
@@ -59,7 +69,10 @@ class Masks_FourTypes_MaskedMem_NonMaskedLib_SmallerMaskGran extends MacroCompil
compileExecuteAndTest(mem, lib, v, output) compileExecuteAndTest(mem, lib, v, output)
} }
class Masks_FourTypes_MaskedMem_MaskedLib extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator { class Masks_FourTypes_MaskedMem_MaskedLib
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024) override lazy val depth = BigInt(1024)
override lazy val memWidth = 32 override lazy val memWidth = 32
override lazy val memMaskGran = Some(8) override lazy val memMaskGran = Some(8)
@@ -69,7 +82,10 @@ class Masks_FourTypes_MaskedMem_MaskedLib extends MacroCompilerSpec with HasSRAM
compileExecuteAndTest(mem, lib, v, output) compileExecuteAndTest(mem, lib, v, output)
} }
class Masks_FourTypes_MaskedMem_MaskedLib_SameMaskGran extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator { class Masks_FourTypes_MaskedMem_MaskedLib_SameMaskGran
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024) override lazy val depth = BigInt(1024)
override lazy val memWidth = 32 override lazy val memWidth = 32
override lazy val memMaskGran = Some(8) override lazy val memMaskGran = Some(8)
@@ -79,7 +95,10 @@ class Masks_FourTypes_MaskedMem_MaskedLib_SameMaskGran extends MacroCompilerSpec
compileExecuteAndTest(mem, lib, v, output) compileExecuteAndTest(mem, lib, v, output)
} }
class Masks_FourTypes_MaskedMem_MaskedLib_SmallerMaskGran extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator { class Masks_FourTypes_MaskedMem_MaskedLib_SmallerMaskGran
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024) override lazy val depth = BigInt(1024)
override lazy val memWidth = 64 override lazy val memWidth = 64
override lazy val memMaskGran = Some(4) override lazy val memMaskGran = Some(4)
@@ -103,7 +122,11 @@ class Masks_BitMaskedMem_NonMaskedLib extends MacroCompilerSpec with HasSRAMGene
// FPGA-style byte-masked memories. // FPGA-style byte-masked memories.
class Masks_FPGAStyle_32_8 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator with MasksTestSettings { class Masks_FPGAStyle_32_8
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 32 override lazy val width = 32
override lazy val memMaskGran = Some(32) override lazy val memMaskGran = Some(32)
override lazy val libMaskGran = Some(8) override lazy val libMaskGran = Some(8)
@@ -113,7 +136,11 @@ class Masks_FPGAStyle_32_8 extends MacroCompilerSpec with HasSRAMGenerator with
// Simple powers of two with bit-masked lib. // Simple powers of two with bit-masked lib.
class Masks_PowersOfTwo_8_1 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator with MasksTestSettings { class Masks_PowersOfTwo_8_1
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 64 override lazy val width = 64
override lazy val memMaskGran = Some(8) override lazy val memMaskGran = Some(8)
override lazy val libMaskGran = Some(1) override lazy val libMaskGran = Some(1)
@@ -121,7 +148,11 @@ class Masks_PowersOfTwo_8_1 extends MacroCompilerSpec with HasSRAMGenerator with
compileExecuteAndTest(mem, lib, v, output) compileExecuteAndTest(mem, lib, v, output)
} }
class Masks_PowersOfTwo_16_1 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator with MasksTestSettings { class Masks_PowersOfTwo_16_1
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 64 override lazy val width = 64
override lazy val memMaskGran = Some(16) override lazy val memMaskGran = Some(16)
override lazy val libMaskGran = Some(1) override lazy val libMaskGran = Some(1)
@@ -129,7 +160,11 @@ class Masks_PowersOfTwo_16_1 extends MacroCompilerSpec with HasSRAMGenerator wit
compileExecuteAndTest(mem, lib, v, output) compileExecuteAndTest(mem, lib, v, output)
} }
class Masks_PowersOfTwo_32_1 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator with MasksTestSettings { class Masks_PowersOfTwo_32_1
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 64 override lazy val width = 64
override lazy val memMaskGran = Some(32) override lazy val memMaskGran = Some(32)
override lazy val libMaskGran = Some(1) override lazy val libMaskGran = Some(1)
@@ -137,7 +172,11 @@ class Masks_PowersOfTwo_32_1 extends MacroCompilerSpec with HasSRAMGenerator wit
compileExecuteAndTest(mem, lib, v, output) compileExecuteAndTest(mem, lib, v, output)
} }
class Masks_PowersOfTwo_64_1 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator with MasksTestSettings { class Masks_PowersOfTwo_64_1
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 64 override lazy val width = 64
override lazy val memMaskGran = Some(64) override lazy val memMaskGran = Some(64)
override lazy val libMaskGran = Some(1) override lazy val libMaskGran = Some(1)
@@ -147,7 +186,11 @@ class Masks_PowersOfTwo_64_1 extends MacroCompilerSpec with HasSRAMGenerator wit
// Simple powers of two with non bit-masked lib. // Simple powers of two with non bit-masked lib.
class Masks_PowersOfTwo_32_4 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator with MasksTestSettings { class Masks_PowersOfTwo_32_4
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 128 override lazy val width = 128
override lazy val memMaskGran = Some(32) override lazy val memMaskGran = Some(32)
override lazy val libMaskGran = Some(4) override lazy val libMaskGran = Some(4)
@@ -155,7 +198,11 @@ class Masks_PowersOfTwo_32_4 extends MacroCompilerSpec with HasSRAMGenerator wit
compileExecuteAndTest(mem, lib, v, output) compileExecuteAndTest(mem, lib, v, output)
} }
class Masks_PowersOfTwo_32_8 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator with MasksTestSettings { class Masks_PowersOfTwo_32_8
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 128 override lazy val width = 128
override lazy val memMaskGran = Some(32) override lazy val memMaskGran = Some(32)
override lazy val libMaskGran = Some(8) override lazy val libMaskGran = Some(8)
@@ -163,7 +210,11 @@ class Masks_PowersOfTwo_32_8 extends MacroCompilerSpec with HasSRAMGenerator wit
compileExecuteAndTest(mem, lib, v, output) compileExecuteAndTest(mem, lib, v, output)
} }
class Masks_PowersOfTwo_8_8 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator with MasksTestSettings { class Masks_PowersOfTwo_8_8
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 128 override lazy val width = 128
override lazy val memMaskGran = Some(8) override lazy val memMaskGran = Some(8)
override lazy val libMaskGran = Some(8) override lazy val libMaskGran = Some(8)
@@ -173,7 +224,11 @@ class Masks_PowersOfTwo_8_8 extends MacroCompilerSpec with HasSRAMGenerator with
// Width as a multiple of the mask, bit-masked lib // Width as a multiple of the mask, bit-masked lib
class Masks_IntegerMaskMultiple_20_10 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator with MasksTestSettings { class Masks_IntegerMaskMultiple_20_10
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 20 override lazy val width = 20
override lazy val memMaskGran = Some(10) override lazy val memMaskGran = Some(10)
override lazy val libMaskGran = Some(1) override lazy val libMaskGran = Some(1)
@@ -181,16 +236,24 @@ class Masks_IntegerMaskMultiple_20_10 extends MacroCompilerSpec with HasSRAMGene
compileExecuteAndTest(mem, lib, v, output) compileExecuteAndTest(mem, lib, v, output)
} }
class Masks_IntegerMaskMultiple_21_7 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator with MasksTestSettings { class Masks_IntegerMaskMultiple_21_7
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 21 override lazy val width = 21
override lazy val memMaskGran = Some(21) override lazy val memMaskGran = Some(21)
override lazy val libMaskGran = Some(7) override lazy val libMaskGran = Some(7)
it should "be enabled when non-power of two masks are supported" is (pending) (it should "be enabled when non-power of two masks are supported").is(pending)
//~ compileExecuteAndTest(mem, lib, v, output) //~ compileExecuteAndTest(mem, lib, v, output)
} }
class Masks_IntegerMaskMultiple_21_21 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator with MasksTestSettings { class Masks_IntegerMaskMultiple_21_21
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 21 override lazy val width = 21
override lazy val memMaskGran = Some(21) override lazy val memMaskGran = Some(21)
override lazy val libMaskGran = Some(1) override lazy val libMaskGran = Some(1)
@@ -198,7 +261,11 @@ class Masks_IntegerMaskMultiple_21_21 extends MacroCompilerSpec with HasSRAMGene
compileExecuteAndTest(mem, lib, v, output) compileExecuteAndTest(mem, lib, v, output)
} }
class Masks_IntegerMaskMultiple_84_21 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator with MasksTestSettings { class Masks_IntegerMaskMultiple_84_21
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 84 override lazy val width = 84
override lazy val memMaskGran = Some(21) override lazy val memMaskGran = Some(21)
override lazy val libMaskGran = Some(1) override lazy val libMaskGran = Some(1)
@@ -206,7 +273,11 @@ class Masks_IntegerMaskMultiple_84_21 extends MacroCompilerSpec with HasSRAMGene
compileExecuteAndTest(mem, lib, v, output) compileExecuteAndTest(mem, lib, v, output)
} }
class Masks_IntegerMaskMultiple_92_23 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator with MasksTestSettings { class Masks_IntegerMaskMultiple_92_23
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 92 override lazy val width = 92
override lazy val memMaskGran = Some(23) override lazy val memMaskGran = Some(23)
override lazy val libMaskGran = Some(1) override lazy val libMaskGran = Some(1)
@@ -214,7 +285,11 @@ class Masks_IntegerMaskMultiple_92_23 extends MacroCompilerSpec with HasSRAMGene
compileExecuteAndTest(mem, lib, v, output) compileExecuteAndTest(mem, lib, v, output)
} }
class Masks_IntegerMaskMultiple_117_13 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator with MasksTestSettings { class Masks_IntegerMaskMultiple_117_13
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 117 override lazy val width = 117
override lazy val memMaskGran = Some(13) override lazy val memMaskGran = Some(13)
override lazy val libMaskGran = Some(1) override lazy val libMaskGran = Some(1)
@@ -222,7 +297,11 @@ class Masks_IntegerMaskMultiple_117_13 extends MacroCompilerSpec with HasSRAMGen
compileExecuteAndTest(mem, lib, v, output) compileExecuteAndTest(mem, lib, v, output)
} }
class Masks_IntegerMaskMultiple_160_20 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator with MasksTestSettings { class Masks_IntegerMaskMultiple_160_20
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 160 override lazy val width = 160
override lazy val memMaskGran = Some(20) override lazy val memMaskGran = Some(20)
override lazy val libMaskGran = Some(1) override lazy val libMaskGran = Some(1)
@@ -230,7 +309,11 @@ class Masks_IntegerMaskMultiple_160_20 extends MacroCompilerSpec with HasSRAMGen
compileExecuteAndTest(mem, lib, v, output) compileExecuteAndTest(mem, lib, v, output)
} }
class Masks_IntegerMaskMultiple_184_23 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator with MasksTestSettings { class Masks_IntegerMaskMultiple_184_23
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 184 override lazy val width = 184
override lazy val memMaskGran = Some(23) override lazy val memMaskGran = Some(23)
override lazy val libMaskGran = Some(1) override lazy val libMaskGran = Some(1)
@@ -240,11 +323,15 @@ class Masks_IntegerMaskMultiple_184_23 extends MacroCompilerSpec with HasSRAMGen
// Width as an non-integer multiple of the mask, bit-masked lib // Width as an non-integer multiple of the mask, bit-masked lib
class Masks_NonIntegerMaskMultiple_32_3 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator with MasksTestSettings { class Masks_NonIntegerMaskMultiple_32_3
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 32 override lazy val width = 32
override lazy val memMaskGran = Some(3) override lazy val memMaskGran = Some(3)
override lazy val libMaskGran = Some(1) override lazy val libMaskGran = Some(1)
it should "be enabled when non-power of two masks are supported" is (pending) (it should "be enabled when non-power of two masks are supported").is(pending)
//~ compileExecuteAndTest(mem, lib, v, output) //~ compileExecuteAndTest(mem, lib, v, output)
} }

View File

@@ -17,15 +17,28 @@ class SplitWidth_2rw extends MacroCompilerSpec with HasSRAMGenerator with HasSim
width = memWidth, width = memWidth,
depth = memDepth, depth = memDepth,
family = "2rw", family = "2rw",
ports=Seq(generateTestPort( ports = Seq(
"portA", memWidth, Some(memDepth), maskGran=memMaskGran, generateTestPort(
write=true, writeEnable=true, "portA",
read=true, readEnable=true memWidth,
), generateTestPort( Some(memDepth),
"portB", memWidth, Some(memDepth), maskGran=memMaskGran, maskGran = memMaskGran,
write=true, writeEnable=true, write = true,
read=true, readEnable=true writeEnable = true,
)) read = true,
readEnable = true
),
generateTestPort(
"portB",
memWidth,
Some(memDepth),
maskGran = memMaskGran,
write = true,
writeEnable = true,
read = true,
readEnable = true
)
)
) )
} }
@@ -35,20 +48,35 @@ class SplitWidth_2rw extends MacroCompilerSpec with HasSRAMGenerator with HasSim
width = libWidth, width = libWidth,
depth = libDepth, depth = libDepth,
family = "2rw", family = "2rw",
ports=Seq(generateTestPort( ports = Seq(
"portA", libWidth, libDepth, generateTestPort(
write=true, writeEnable=true, "portA",
read=true, readEnable=true libWidth,
), generateTestPort( libDepth,
"portB", libWidth, libDepth, write = true,
write=true, writeEnable=true, writeEnable = true,
read=true, readEnable=true read = true,
)) readEnable = true
),
generateTestPort(
"portB",
libWidth,
libDepth,
write = true,
writeEnable = true,
read = true,
readEnable = true
)
)
) )
} }
override def generateHeaderPorts() = { override def generateHeaderPorts() = {
generateReadWriteHeaderPort("portA", true, Some(memMaskBits)) + "\n" + generateReadWriteHeaderPort("portB", true, Some(memMaskBits)) generateReadWriteHeaderPort("portA", true, Some(memMaskBits)) + "\n" + generateReadWriteHeaderPort(
"portB",
true,
Some(memMaskBits)
)
} }
override def generateFooterPorts() = { override def generateFooterPorts() = {
@@ -132,15 +160,28 @@ class SplitWidth_1r_1w extends MacroCompilerSpec with HasSRAMGenerator with HasS
width = memWidth, width = memWidth,
depth = memDepth, depth = memDepth,
family = "1r1w", family = "1r1w",
ports=Seq(generateTestPort( ports = Seq(
"portA", memWidth, Some(memDepth), maskGran=memMaskGran, generateTestPort(
write=false, writeEnable=false, "portA",
read=true, readEnable=true memWidth,
), generateTestPort( Some(memDepth),
"portB", memWidth, Some(memDepth), maskGran=memMaskGran, maskGran = memMaskGran,
write=true, writeEnable=true, write = false,
read=false, readEnable=false writeEnable = false,
)) read = true,
readEnable = true
),
generateTestPort(
"portB",
memWidth,
Some(memDepth),
maskGran = memMaskGran,
write = true,
writeEnable = true,
read = false,
readEnable = false
)
)
) )
} }
@@ -150,30 +191,73 @@ class SplitWidth_1r_1w extends MacroCompilerSpec with HasSRAMGenerator with HasS
width = libWidth, width = libWidth,
depth = libDepth, depth = libDepth,
family = "1r1w", family = "1r1w",
ports=Seq(generateTestPort( ports = Seq(
"portA", libWidth, libDepth, generateTestPort(
write=false, writeEnable=false, "portA",
read=true, readEnable=true libWidth,
), generateTestPort( libDepth,
"portB", libWidth, libDepth, write = false,
write=true, writeEnable=true, writeEnable = false,
read=false, readEnable=false read = true,
)) readEnable = true
),
generateTestPort(
"portB",
libWidth,
libDepth,
write = true,
writeEnable = true,
read = false,
readEnable = false
)
)
) )
} }
override def generateHeaderPorts() = { override def generateHeaderPorts() = {
generatePort("portA", mem_addr_width, memWidth, generatePort(
write=false, writeEnable=false, read=true, readEnable=true, Some(memMaskBits)) + "\n" + "portA",
generatePort("portB", mem_addr_width, memWidth, mem_addr_width,
write=true, writeEnable=true, read=false, readEnable=false, Some(memMaskBits)) memWidth,
write = false,
writeEnable = false,
read = true,
readEnable = true,
Some(memMaskBits)
) + "\n" +
generatePort(
"portB",
mem_addr_width,
memWidth,
write = true,
writeEnable = true,
read = false,
readEnable = false,
Some(memMaskBits)
)
} }
override def generateFooterPorts() = { override def generateFooterPorts() = {
generatePort("portA", lib_addr_width, libWidth, generatePort(
write=false, writeEnable=false, read=true, readEnable=true, None) + "\n" + "portA",
generatePort("portB", lib_addr_width, libWidth, lib_addr_width,
write=true, writeEnable=true, read=false, readEnable=false, None) libWidth,
write = false,
writeEnable = false,
read = true,
readEnable = true,
None
) + "\n" +
generatePort(
"portB",
lib_addr_width,
libWidth,
write = true,
writeEnable = true,
read = false,
readEnable = false,
None
)
} }
override def generateBody() = override def generateBody() =
@@ -238,15 +322,28 @@ class SplitWidth_2rw_differentMasks extends MacroCompilerSpec with HasSRAMGenera
width = memWidth, width = memWidth,
depth = memDepth, depth = memDepth,
family = "2rw", family = "2rw",
ports=Seq(generateTestPort( ports = Seq(
"portA", memWidth, Some(memDepth), maskGran=memMaskGran, generateTestPort(
write=true, writeEnable=true, "portA",
read=true, readEnable=true memWidth,
), generateTestPort( Some(memDepth),
"portB", memWidth, Some(memDepth), maskGran=Some(memMaskGranB), maskGran = memMaskGran,
write=true, writeEnable=true, write = true,
read=true, readEnable=true writeEnable = true,
)) read = true,
readEnable = true
),
generateTestPort(
"portB",
memWidth,
Some(memDepth),
maskGran = Some(memMaskGranB),
write = true,
writeEnable = true,
read = true,
readEnable = true
)
)
) )
} }
@@ -256,20 +353,35 @@ class SplitWidth_2rw_differentMasks extends MacroCompilerSpec with HasSRAMGenera
width = libWidth, width = libWidth,
depth = libDepth, depth = libDepth,
family = "2rw", family = "2rw",
ports=Seq(generateTestPort( ports = Seq(
"portA", libWidth, libDepth, generateTestPort(
write=true, writeEnable=true, "portA",
read=true, readEnable=true libWidth,
), generateTestPort( libDepth,
"portB", libWidth, libDepth, write = true,
write=true, writeEnable=true, writeEnable = true,
read=true, readEnable=true read = true,
)) readEnable = true
),
generateTestPort(
"portB",
libWidth,
libDepth,
write = true,
writeEnable = true,
read = true,
readEnable = true
)
)
) )
} }
override def generateHeaderPorts() = { override def generateHeaderPorts() = {
generateReadWriteHeaderPort("portA", true, Some(memMaskBits)) + "\n" + generateReadWriteHeaderPort("portB", true, Some(memWidth / memMaskGranB)) generateReadWriteHeaderPort("portA", true, Some(memMaskBits)) + "\n" + generateReadWriteHeaderPort(
"portB",
true,
Some(memWidth / memMaskGranB)
)
} }
override def generateFooterPorts() = { override def generateFooterPorts() = {

View File

@@ -13,7 +13,6 @@ class SRAMCompiler extends MacroCompilerSpec with HasSRAMGenerator with HasSimpl
writeToLib(lib, Seq(compiler)) writeToLib(lib, Seq(compiler))
writeToMem(mem, Seq(generateSRAM("mymem", "X", 8, 16))) writeToMem(mem, Seq(generateSRAM("mymem", "X", 8, 16)))
compileExecuteAndTest(mem, Some(lib), verilog, output = output, false, true) compileExecuteAndTest(mem, Some(lib), verilog, output = output, false, true)

View File

@@ -28,9 +28,12 @@ s"""
for (i <- 0 to depthInstances - 1) { for (i <- 0 to depthInstances - 1) {
val maskStatement = generateMaskStatement(0, i) val maskStatement = generateMaskStatement(0, i)
val enableIdentifier = if (selectBits > 0) s"""eq(${memPortPrefix}_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\")"
val chipEnable = s"""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" val writeEnable =
if (memMaskGran.isEmpty) s"and(${memPortPrefix}_write_en, ${chipEnable})" else s"${memPortPrefix}_write_en"
output.append( output.append(
s""" s"""
inst mem_${i}_0 of ${lib_name} inst mem_${i}_0 of ${lib_name}
@@ -49,15 +52,18 @@ s"""
s"""UInt<${libWidth}>("h0")""" s"""UInt<${libWidth}>("h0")"""
} else { } else {
s"""mux(eq(${memPortPrefix}_addr_sel_reg, UInt<%d>("h%s")), ${memPortPrefix}_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) selectBits,
i.toHexString,
i,
generate_outer_dout_tree(i + 1, depthInstances)
) )
} }
} }
output append s" ${memPortPrefix}_dout <= " output.append(s" ${memPortPrefix}_dout <= ")
if (selectBits > 0) { if (selectBits > 0) {
output append generate_outer_dout_tree(0, depthInstances) output.append(generate_outer_dout_tree(0, depthInstances))
} else { } 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 output.toString
@@ -154,7 +160,10 @@ class SplitDepth2048x8_mrw_lib8 extends MacroCompilerSpec with HasSRAMGenerator
} }
// Non-bit level mask // Non-bit level mask
class SplitDepth2048x64_mrw_mem32_lib8 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator { class SplitDepth2048x64_mrw_mem32_lib8
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator {
override lazy val width = 64 override lazy val width = 64
override lazy val memDepth = BigInt(2048) override lazy val memDepth = BigInt(2048)
override lazy val libDepth = BigInt(1024) override lazy val libDepth = BigInt(1024)
@@ -165,7 +174,10 @@ class SplitDepth2048x64_mrw_mem32_lib8 extends MacroCompilerSpec with HasSRAMGen
} }
// Bit level mask // Bit level mask
class SplitDepth2048x32_mrw_mem16_lib1 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator { class SplitDepth2048x32_mrw_mem16_lib1
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator {
override lazy val width = 32 override lazy val width = 32
override lazy val memDepth = BigInt(2048) override lazy val memDepth = BigInt(2048)
override lazy val libDepth = BigInt(1024) override lazy val libDepth = BigInt(1024)
@@ -213,7 +225,7 @@ class SplitDepth2048x32_mrw_mem3_lib1 extends MacroCompilerSpec with HasSRAMGene
override lazy val memMaskGran = Some(3) override lazy val memMaskGran = Some(3)
override lazy val libMaskGran = Some(1) override lazy val libMaskGran = Some(1)
it should "be enabled when non-power of two masks are supported" is (pending) (it should "be enabled when non-power of two masks are supported").is(pending)
//compileExecuteAndTest(mem, lib, v, output) //compileExecuteAndTest(mem, lib, v, output)
} }
@@ -224,7 +236,7 @@ class SplitDepth2048x32_mrw_mem7_lib1 extends MacroCompilerSpec with HasSRAMGene
override lazy val memMaskGran = Some(7) override lazy val memMaskGran = Some(7)
override lazy val libMaskGran = Some(1) override lazy val libMaskGran = Some(1)
it should "be enabled when non-power of two masks are supported" is (pending) (it should "be enabled when non-power of two masks are supported").is(pending)
//compileExecuteAndTest(mem, lib, v, output) //compileExecuteAndTest(mem, lib, v, output)
} }
@@ -235,7 +247,7 @@ class SplitDepth2048x32_mrw_mem9_lib1 extends MacroCompilerSpec with HasSRAMGene
override lazy val memMaskGran = Some(9) override lazy val memMaskGran = Some(9)
override lazy val libMaskGran = Some(1) override lazy val libMaskGran = Some(1)
it should "be enabled when non-power of two masks are supported" is (pending) (it should "be enabled when non-power of two masks are supported").is(pending)
//compileExecuteAndTest(mem, lib, v, output) //compileExecuteAndTest(mem, lib, v, output)
} }

View File

@@ -15,14 +15,15 @@ trait HasSimpleWidthTestGenerator extends HasSimpleTestGenerator {
// Generate mem_0_<i> lines for number of width instances. // Generate mem_0_<i> lines for number of width instances.
output.append( output.append(
((0 to widthInstances - 1) map {i:Int => s""" ((0 to widthInstances - 1).map { i: Int =>
s"""
inst mem_0_${i} of ${lib_name} inst mem_0_${i} of ${lib_name}
""" """
}).reduceLeft(_ + _) }).reduceLeft(_ + _)
) )
// Generate submemory connection blocks. // Generate submemory connection blocks.
output append (for (i <- 0 to widthInstances - 1) yield { output.append((for (i <- 0 to widthInstances - 1) yield {
// Width of this submemory. // Width of this submemory.
val myMemWidth = if (i == widthInstances - 1) lastWidthBits else usableLibWidth val myMemWidth = if (i == widthInstances - 1) lastWidthBits else usableLibWidth
// Base bit of this submemory. // Base bit of this submemory.
@@ -39,7 +40,8 @@ trait HasSimpleWidthTestGenerator extends HasSimpleTestGenerator {
s"bits(outer_mask, ${outerMaskBit}, ${outerMaskBit})" s"bits(outer_mask, ${outerMaskBit}, ${outerMaskBit})"
} else """UInt<1>("h1")""" } else """UInt<1>("h1")"""
val chipEnable = s"""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" val writeEnableExpr =
if (libMaskGran.isEmpty) s"and(${memPortPrefix}_write_en, ${chipEnable})" else s"${memPortPrefix}_write_en"
s""" s"""
mem_0_${i}.${libPortPrefix}_clk <= ${memPortPrefix}_clk mem_0_${i}.${libPortPrefix}_clk <= ${memPortPrefix}_clk
@@ -49,22 +51,21 @@ s"""
${maskStatement} ${maskStatement}
mem_0_${i}.${libPortPrefix}_write_en <= and(and(${writeEnableExpr}, ${writeEnableBit}), UInt<1>("h1")) mem_0_${i}.${libPortPrefix}_write_en <= and(and(${writeEnableExpr}, ${writeEnableBit}), UInt<1>("h1"))
""" """
}).reduceLeft(_ + _) }).reduceLeft(_ + _))
// Generate final output that concats together the sub-memories. // 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)) // e.g. cat(outer_dout_0_2, cat(outer_dout_0_1, outer_dout_0_0))
output append { 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)") val catStmt = doutStatements.init.foldRight(doutStatements.last)((l: String, r: String) => s"cat($l, $r)")
s""" s"""
node ${memPortPrefix}_dout_0 = ${catStmt} node ${memPortPrefix}_dout_0 = ${catStmt}
""" """
} }
output append output.append(s"""
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 output.toString
} }
} }
@@ -268,7 +269,10 @@ class SplitWidth1024x16_mem11_rw extends MacroCompilerSpec with HasSRAMGenerator
// Masked RAM // Masked RAM
class SplitWidth1024x8_memGran_8_libGran_1_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator { class SplitWidth1024x8_memGran_8_libGran_1_rw
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024) override lazy val depth = BigInt(1024)
override lazy val memWidth = 8 override lazy val memWidth = 8
override lazy val libWidth = 8 override lazy val libWidth = 8
@@ -278,7 +282,10 @@ class SplitWidth1024x8_memGran_8_libGran_1_rw extends MacroCompilerSpec with Has
compileExecuteAndTest(mem, lib, v, output) compileExecuteAndTest(mem, lib, v, output)
} }
class SplitWidth1024x16_memGran_8_libGran_1_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator { class SplitWidth1024x16_memGran_8_libGran_1_rw
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024) override lazy val depth = BigInt(1024)
override lazy val memWidth = 16 override lazy val memWidth = 16
override lazy val libWidth = 8 override lazy val libWidth = 8
@@ -288,7 +295,10 @@ class SplitWidth1024x16_memGran_8_libGran_1_rw extends MacroCompilerSpec with Ha
compileExecuteAndTest(mem, lib, v, output) compileExecuteAndTest(mem, lib, v, output)
} }
class SplitWidth1024x16_memGran_8_libGran_8_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator { class SplitWidth1024x16_memGran_8_libGran_8_rw
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024) override lazy val depth = BigInt(1024)
override lazy val memWidth = 16 override lazy val memWidth = 16
override lazy val libWidth = 8 override lazy val libWidth = 8
@@ -298,7 +308,10 @@ class SplitWidth1024x16_memGran_8_libGran_8_rw extends MacroCompilerSpec with Ha
compileExecuteAndTest(mem, lib, v, output) compileExecuteAndTest(mem, lib, v, output)
} }
class SplitWidth1024x128_memGran_8_libGran_1_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator { class SplitWidth1024x128_memGran_8_libGran_1_rw
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024) override lazy val depth = BigInt(1024)
override lazy val memWidth = 128 override lazy val memWidth = 128
override lazy val libWidth = 32 override lazy val libWidth = 32
@@ -308,7 +321,10 @@ class SplitWidth1024x128_memGran_8_libGran_1_rw extends MacroCompilerSpec with H
compileExecuteAndTest(mem, lib, v, output) compileExecuteAndTest(mem, lib, v, output)
} }
class SplitWidth1024x16_memGran_4_libGran_1_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator { class SplitWidth1024x16_memGran_4_libGran_1_rw
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024) override lazy val depth = BigInt(1024)
override lazy val memWidth = 16 override lazy val memWidth = 16
override lazy val libWidth = 8 override lazy val libWidth = 8
@@ -318,7 +334,10 @@ class SplitWidth1024x16_memGran_4_libGran_1_rw extends MacroCompilerSpec with Ha
compileExecuteAndTest(mem, lib, v, output) compileExecuteAndTest(mem, lib, v, output)
} }
class SplitWidth1024x16_memGran_2_libGran_1_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator { class SplitWidth1024x16_memGran_2_libGran_1_rw
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024) override lazy val depth = BigInt(1024)
override lazy val memWidth = 16 override lazy val memWidth = 16
override lazy val libWidth = 8 override lazy val libWidth = 8
@@ -328,7 +347,10 @@ class SplitWidth1024x16_memGran_2_libGran_1_rw extends MacroCompilerSpec with Ha
compileExecuteAndTest(mem, lib, v, output) compileExecuteAndTest(mem, lib, v, output)
} }
class SplitWidth1024x16_memGran_16_libGran_1_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator { class SplitWidth1024x16_memGran_16_libGran_1_rw
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024) override lazy val depth = BigInt(1024)
override lazy val memWidth = 16 override lazy val memWidth = 16
override lazy val libWidth = 8 override lazy val libWidth = 8
@@ -360,7 +382,10 @@ class SplitWidth1024x16_libGran_1_rw extends MacroCompilerSpec with HasSRAMGener
// Non-memMask and non-1 libMask // Non-memMask and non-1 libMask
class SplitWidth1024x16_memGran_8_libGran_2_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator { class SplitWidth1024x16_memGran_8_libGran_2_rw
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024) override lazy val depth = BigInt(1024)
override lazy val memWidth = 16 override lazy val memWidth = 16
override lazy val libWidth = 8 override lazy val libWidth = 8
@@ -372,21 +397,27 @@ class SplitWidth1024x16_memGran_8_libGran_2_rw extends MacroCompilerSpec with Ha
// Non-power of two memGran // Non-power of two memGran
class SplitWidth1024x16_memGran_9_libGran_1_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator { class SplitWidth1024x16_memGran_9_libGran_1_rw
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024) override lazy val depth = BigInt(1024)
override lazy val memWidth = 16 override lazy val memWidth = 16
override lazy val libWidth = 8 override lazy val libWidth = 8
override lazy val memMaskGran = Some(9) override lazy val memMaskGran = Some(9)
override lazy val libMaskGran = Some(1) override lazy val libMaskGran = Some(1)
it should "be enabled when non-power of two masks are supported" is (pending) (it should "be enabled when non-power of two masks are supported").is(pending)
//~ compile(mem, lib, v, false) //~ compile(mem, lib, v, false)
//~ execute(mem, lib, false, output) //~ execute(mem, lib, false, output)
} }
// Read enable // Read enable
class SplitWidth1024x32_readEnable_Lib extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator { class SplitWidth1024x32_readEnable_Lib
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
import mdf.macrolib._ import mdf.macrolib._
override lazy val depth = BigInt(1024) override lazy val depth = BigInt(1024)
@@ -399,11 +430,18 @@ class SplitWidth1024x32_readEnable_Lib extends MacroCompilerSpec with HasSRAMGen
width = libWidth, width = libWidth,
depth = libDepth, depth = libDepth,
family = "1rw", family = "1rw",
ports=Seq(generateTestPort( ports = Seq(
"lib", Some(libWidth), Some(libDepth), maskGran=libMaskGran, generateTestPort(
write=true, writeEnable=true, "lib",
read=true, readEnable=true Some(libWidth),
)) Some(libDepth),
maskGran = libMaskGran,
write = true,
writeEnable = true,
read = true,
readEnable = true
)
)
) )
} }
@@ -444,7 +482,10 @@ class SplitWidth1024x32_readEnable_Lib extends MacroCompilerSpec with HasSRAMGen
compileExecuteAndTest(mem, lib, v, output) compileExecuteAndTest(mem, lib, v, output)
} }
class SplitWidth1024x32_readEnable_Mem extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator { class SplitWidth1024x32_readEnable_Mem
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
import mdf.macrolib._ import mdf.macrolib._
override lazy val depth = BigInt(1024) override lazy val depth = BigInt(1024)
@@ -457,11 +498,18 @@ class SplitWidth1024x32_readEnable_Mem extends MacroCompilerSpec with HasSRAMGen
width = memWidth, width = memWidth,
depth = memDepth, depth = memDepth,
family = "1rw", family = "1rw",
ports=Seq(generateTestPort( ports = Seq(
"outer", Some(memWidth), Some(memDepth), maskGran=memMaskGran, generateTestPort(
write=true, writeEnable=true, "outer",
read=true, readEnable=true Some(memWidth),
)) Some(memDepth),
maskGran = memMaskGran,
write = true,
writeEnable = true,
read = true,
readEnable = true
)
)
) )
} }
@@ -470,7 +518,10 @@ class SplitWidth1024x32_readEnable_Mem extends MacroCompilerSpec with HasSRAMGen
compileExecuteAndTest(mem, lib, v, output) compileExecuteAndTest(mem, lib, v, output)
} }
class SplitWidth1024x32_readEnable_LibMem extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator { class SplitWidth1024x32_readEnable_LibMem
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
import mdf.macrolib._ import mdf.macrolib._
override lazy val depth = BigInt(1024) override lazy val depth = BigInt(1024)
@@ -483,11 +534,18 @@ class SplitWidth1024x32_readEnable_LibMem extends MacroCompilerSpec with HasSRAM
width = libWidth, width = libWidth,
depth = libDepth, depth = libDepth,
family = "1rw", family = "1rw",
ports=Seq(generateTestPort( ports = Seq(
"lib", Some(libWidth), Some(libDepth), maskGran=libMaskGran, generateTestPort(
write=true, writeEnable=true, "lib",
read=true, readEnable=true Some(libWidth),
)) Some(libDepth),
maskGran = libMaskGran,
write = true,
writeEnable = true,
read = true,
readEnable = true
)
)
) )
} }
@@ -497,11 +555,18 @@ class SplitWidth1024x32_readEnable_LibMem extends MacroCompilerSpec with HasSRAM
width = memWidth, width = memWidth,
depth = memDepth, depth = memDepth,
family = "1rw", family = "1rw",
ports=Seq(generateTestPort( ports = Seq(
"outer", Some(memWidth), Some(memDepth), maskGran=memMaskGran, generateTestPort(
write=true, writeEnable=true, "outer",
read=true, readEnable=true Some(memWidth),
)) Some(memDepth),
maskGran = memMaskGran,
write = true,
writeEnable = true,
read = true,
readEnable = true
)
)
) )
} }

View File

@@ -29,8 +29,8 @@ class WriteEnableTest extends MacroCompilerSpec with HasSRAMGenerator {
override val libPrefix = "macros/src/test/resources" override val libPrefix = "macros/src/test/resources"
val memSRAMs = mdf.macrolib.Utils.readMDFFromString( val memSRAMs = mdf.macrolib.Utils
""" .readMDFFromString("""
[ { [ {
"type" : "sram", "type" : "sram",
"name" : "cc_banks_0_ext", "name" : "cc_banks_0_ext",
@@ -99,8 +99,8 @@ class MaskPortTest extends MacroCompilerSpec with HasSRAMGenerator {
override val libPrefix = "macros/src/test/resources" override val libPrefix = "macros/src/test/resources"
val memSRAMs = mdf.macrolib.Utils.readMDFFromString( val memSRAMs = mdf.macrolib.Utils
""" .readMDFFromString("""
[ { [ {
"type" : "sram", "type" : "sram",
"name" : "cc_dir_ext", "name" : "cc_dir_ext",
@@ -183,8 +183,8 @@ class BOOMTest extends MacroCompilerSpec with HasSRAMGenerator {
override val libPrefix = "macros/src/test/resources" override val libPrefix = "macros/src/test/resources"
val memSRAMs = mdf.macrolib.Utils.readMDFFromString( val memSRAMs = mdf.macrolib.Utils
""" .readMDFFromString("""
[ { [ {
"type" : "sram", "type" : "sram",
"name" : "_T_182_ext", "name" : "_T_182_ext",
@@ -1453,8 +1453,8 @@ class RocketChipTest extends MacroCompilerSpec with HasSRAMGenerator {
) )
) )
val memSRAMs = mdf.macrolib.Utils.readMDFFromString( val memSRAMs = mdf.macrolib.Utils
""" .readMDFFromString("""
[ [
{ {
"type": "sram", "type": "sram",

View File

@@ -47,7 +47,8 @@ s"""
// If there is no lib, don't generate a footer, since the flops definition // If there is no lib, don't generate a footer, since the flops definition
// will be in the body. // will be in the body.
override def generateFooter = { override def generateFooter = {
if (this.isInstanceOf[HasNoLibTestGenerator]) "" else if (this.isInstanceOf[HasNoLibTestGenerator]) ""
else
s""" s"""
module ${lib_name} : module ${lib_name} :
${generateFooterPorts} ${generateFooterPorts}
@@ -58,28 +59,44 @@ ${generateFlops}
} }
class Synflops2048x8_noLib extends MacroCompilerSpec with HasSRAMGenerator with HasNoLibTestGenerator with HasSynFlopsTestGenerator { class Synflops2048x8_noLib
extends MacroCompilerSpec
with HasSRAMGenerator
with HasNoLibTestGenerator
with HasSynFlopsTestGenerator {
override lazy val memDepth = BigInt(2048) override lazy val memDepth = BigInt(2048)
override lazy val memWidth = 8 override lazy val memWidth = 8
compileExecuteAndTest(mem, None, v, output, true) compileExecuteAndTest(mem, None, v, output, true)
} }
class Synflops2048x16_noLib extends MacroCompilerSpec with HasSRAMGenerator with HasNoLibTestGenerator with HasSynFlopsTestGenerator { class Synflops2048x16_noLib
extends MacroCompilerSpec
with HasSRAMGenerator
with HasNoLibTestGenerator
with HasSynFlopsTestGenerator {
override lazy val memDepth = BigInt(2048) override lazy val memDepth = BigInt(2048)
override lazy val memWidth = 16 override lazy val memWidth = 16
compileExecuteAndTest(mem, None, v, output, true) compileExecuteAndTest(mem, None, v, output, true)
} }
class Synflops8192x16_noLib extends MacroCompilerSpec with HasSRAMGenerator with HasNoLibTestGenerator with HasSynFlopsTestGenerator { class Synflops8192x16_noLib
extends MacroCompilerSpec
with HasSRAMGenerator
with HasNoLibTestGenerator
with HasSynFlopsTestGenerator {
override lazy val memDepth = BigInt(8192) override lazy val memDepth = BigInt(8192)
override lazy val memWidth = 16 override lazy val memWidth = 16
compileExecuteAndTest(mem, None, v, output, true) compileExecuteAndTest(mem, None, v, output, true)
} }
class Synflops2048x16_depth_Lib extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator with HasSynFlopsTestGenerator { class Synflops2048x16_depth_Lib
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with HasSynFlopsTestGenerator {
override lazy val memDepth = BigInt(2048) override lazy val memDepth = BigInt(2048)
override lazy val libDepth = BigInt(1024) override lazy val libDepth = BigInt(1024)
override lazy val width = 16 override lazy val width = 16
@@ -87,7 +104,11 @@ class Synflops2048x16_depth_Lib extends MacroCompilerSpec with HasSRAMGenerator
compileExecuteAndTest(mem, lib, v, output, true) compileExecuteAndTest(mem, lib, v, output, true)
} }
class Synflops2048x64_width_Lib extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator with HasSynFlopsTestGenerator { class Synflops2048x64_width_Lib
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator
with HasSynFlopsTestGenerator {
override lazy val memWidth = 64 override lazy val memWidth = 64
override lazy val libWidth = 8 override lazy val libWidth = 8
override lazy val depth = BigInt(1024) override lazy val depth = BigInt(1024)
@@ -95,7 +116,11 @@ class Synflops2048x64_width_Lib extends MacroCompilerSpec with HasSRAMGenerator
compileExecuteAndTest(mem, lib, v, output, true) compileExecuteAndTest(mem, lib, v, output, true)
} }
class Synflops_SplitPorts_Read_Write extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator with HasSynFlopsTestGenerator { class Synflops_SplitPorts_Read_Write
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with HasSynFlopsTestGenerator {
import mdf.macrolib._ import mdf.macrolib._
override lazy val memDepth = BigInt(2048) override lazy val memDepth = BigInt(2048)
@@ -222,7 +247,11 @@ circuit target_memory :
} }
} }
class Synflops_SplitPorts_MaskedMem_Read_MaskedWrite extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator with HasSynFlopsTestGenerator { class Synflops_SplitPorts_MaskedMem_Read_MaskedWrite
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with HasSynFlopsTestGenerator {
import mdf.macrolib._ import mdf.macrolib._
override lazy val memDepth = BigInt(2048) override lazy val memDepth = BigInt(2048)