Reformat all scala files in macros
- Mostly this reformat comments and large argument lists to classes and methods
This commit is contained in:
@@ -2,15 +2,14 @@
|
||||
|
||||
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.
|
||||
*/
|
||||
// TODO: eventually explore compiling a single target memory using multiple
|
||||
// different kinds of target memory.
|
||||
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.
|
||||
*
|
||||
* @param mem Memory macro to compile (target memory)
|
||||
@@ -20,8 +19,7 @@ trait CostMetric extends Serializable {
|
||||
*/
|
||||
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]
|
||||
|
||||
@@ -41,7 +39,8 @@ trait CostMetricCompanion {
|
||||
|
||||
/** Palmer's old metric.
|
||||
* 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 {
|
||||
override def cost(mem: Macro, lib: Macro): Option[Double] = {
|
||||
/* 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
|
||||
}
|
||||
|
||||
/**
|
||||
* An external cost function.
|
||||
/** An external cost function.
|
||||
* Calls the specified path with paths to the JSON MDF representation of the mem
|
||||
* and lib macros. The external executable should print a Double.
|
||||
* 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
|
||||
object DefaultMetric extends CostMetric with CostMetricCompanion {
|
||||
override def cost(mem: Macro, lib: Macro): Option[Double] = {
|
||||
val memMask = mem.src.ports map (_.maskGran) find (_.isDefined) map (_.get)
|
||||
val libMask = lib.src.ports map (_.maskGran) find (_.isDefined) map (_.get)
|
||||
val memMask = mem.src.ports.map(_.maskGran).find(_.isDefined).map(_.get)
|
||||
val libMask = lib.src.ports.map(_.maskGran).find(_.isDefined).map(_.get)
|
||||
val memWidth = (memMask, libMask) match {
|
||||
case (None, _) => mem.src.width
|
||||
case (Some(p), None) => (mem.src.width/p)*math.ceil(p.toDouble/lib.src.width)*lib.src.width //We map the mask to distinct memories
|
||||
case (Some(p), None) =>
|
||||
(mem.src.width / p) * math.ceil(
|
||||
p.toDouble / lib.src.width
|
||||
) * lib.src.width //We map the mask to distinct memories
|
||||
case (Some(p), Some(m)) => {
|
||||
if (m <= p) (mem.src.width / p) * math.ceil(p.toDouble / m) * m //Using multiple m's to create a p (integeraly)
|
||||
else (mem.src.width / p) * m //Waste the extra maskbits
|
||||
@@ -148,7 +149,8 @@ object MacroCompilerUtil {
|
||||
// Adapted from https://stackoverflow.com/a/134918
|
||||
|
||||
/** 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 = {
|
||||
val baos: ByteArrayOutputStream = new ByteArrayOutputStream
|
||||
val oos: ObjectOutputStream = new ObjectOutputStream(baos)
|
||||
@@ -168,6 +170,7 @@ object MacroCompilerUtil {
|
||||
}
|
||||
|
||||
object CostMetric {
|
||||
|
||||
/** Define some default metric. */
|
||||
val default: CostMetric = DefaultMetric
|
||||
|
||||
@@ -178,8 +181,7 @@ object CostMetric {
|
||||
registerCostMetric(ExternalMetric)
|
||||
registerCostMetric(DefaultMetric)
|
||||
|
||||
/**
|
||||
* Register a cost metric.
|
||||
/** Register a cost metric.
|
||||
* @param createFuncHelper Companion object to fetch the name and construct
|
||||
* the metric.
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// See LICENSE for license details.
|
||||
|
||||
/**
|
||||
* Terminology note:
|
||||
/** Terminology note:
|
||||
* mem - target memory to compile, in design (e.g. Mem() in rocket)
|
||||
* 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]
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* compilation. It simply holds all the settings for the memory compiler. The
|
||||
* actual selection of which memories to compile is set in the Params.
|
||||
*
|
||||
* To use, simply annotate the entire circuit itself with this annotation and
|
||||
* include [[MacroCompilerTransform]].
|
||||
*
|
||||
*/
|
||||
object MacroCompilerAnnotation {
|
||||
|
||||
/** Macro compiler mode. */
|
||||
sealed trait CompilerMode
|
||||
|
||||
/** Strict mode - must compile all memories or error out. */
|
||||
case object Strict extends CompilerMode
|
||||
|
||||
/** Synflops mode - compile all memories with synflops (do not map to lib at all). */
|
||||
case object Synflops extends CompilerMode
|
||||
|
||||
/** CompileAndSynflops mode - compile all memories and create mock versions of the target libs with synflops. */
|
||||
case object CompileAndSynflops extends CompilerMode
|
||||
|
||||
/** FallbackSynflops - compile all memories to SRAM when possible and fall back to synflops if a memory fails. * */
|
||||
case object FallbackSynflops extends CompilerMode
|
||||
|
||||
/** CompileAvailable - compile what is possible and do nothing with uncompiled memories. * */
|
||||
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
|
||||
* vlsi_mem_gen-like scripts) once it's implemented?
|
||||
*/
|
||||
@@ -65,20 +66,37 @@ object MacroCompilerAnnotation {
|
||||
val options: Seq[(CompilerMode, String, String)] = Seq(
|
||||
(Default, "default", "Select the default option from below."),
|
||||
(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."),
|
||||
(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)")
|
||||
(
|
||||
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."
|
||||
),
|
||||
(
|
||||
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. */
|
||||
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 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 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 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],
|
||||
costMetric: CostMetric, mode: CompilerMode, useCompiler: Boolean,
|
||||
forceCompile: Set[String], forceSynflops: Set[String])
|
||||
case class Params(
|
||||
mem: 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 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]],
|
||||
compilers: Option[SRAMCompiler],
|
||||
hammerIR: Option[String],
|
||||
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.
|
||||
// e.g. ((0,21), (22,43)) is legal
|
||||
// ((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.
|
||||
* 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.
|
||||
@@ -132,7 +157,7 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
|
||||
* @return Bit pairs or empty list if there was an error.
|
||||
*/
|
||||
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)]()
|
||||
var currentLSB: BigInt = 0
|
||||
@@ -203,7 +228,9 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
|
||||
splitMemory(memMask.get)
|
||||
} else {
|
||||
// e.g. mem mask = 13, lib width = 8
|
||||
System.err.println(s"Unmasked target memory: unaligned mem maskGran $p with lib (${lib.src.name}) width ${libPort.src.width.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()
|
||||
}
|
||||
}
|
||||
@@ -266,9 +293,11 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
|
||||
}
|
||||
|
||||
def compile(mem: Macro, lib: Macro): Option[(Module, Macro)] = {
|
||||
assert(mem.sortedPorts.lengthCompare(lib.sortedPorts.length) == 0,
|
||||
"mem and lib should have an equal number of ports")
|
||||
val pairedPorts = mem.sortedPorts zip lib.sortedPorts
|
||||
assert(
|
||||
mem.sortedPorts.lengthCompare(lib.sortedPorts.length) == 0,
|
||||
"mem and lib should have an equal number of ports"
|
||||
)
|
||||
val pairedPorts = mem.sortedPorts.zip(lib.sortedPorts)
|
||||
|
||||
// Width mapping. See calculateBitPairs.
|
||||
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
|
||||
* address bits into account. */
|
||||
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 low = MacroCompilerMath.ceilLog2(lib.src.depth)
|
||||
val ref = WRef(port.address.name)
|
||||
@@ -317,18 +346,18 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
|
||||
// Create the instance.
|
||||
stmts += WDefInstance(NoInfo, name, lib.src.name, lib.tpe)
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
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 Some(addr) =>
|
||||
val index = UIntLiteral(i, IntWidth(bitWidth(addr.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 Some(reg) =>
|
||||
val index = UIntLiteral(i, IntWidth(bitWidth(reg.tpe)))
|
||||
@@ -341,29 +370,22 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
|
||||
for (((low, high), j) <- bitPairs.zipWithIndex) {
|
||||
val inst = WRef(s"mem_${i}_${j}", lib.tpe)
|
||||
|
||||
def connectPorts2(mem: Expression,
|
||||
lib: String,
|
||||
polarity: Option[PortPolarity]): Statement =
|
||||
def connectPorts2(mem: Expression, lib: String, polarity: Option[PortPolarity]): Statement =
|
||||
Connect(NoInfo, WSubField(inst, lib), portToExpression(mem, polarity))
|
||||
def connectPorts(mem: Expression,
|
||||
lib: String,
|
||||
polarity: PortPolarity): Statement =
|
||||
def connectPorts(mem: Expression, lib: String, polarity: PortPolarity): Statement =
|
||||
connectPorts2(mem, lib, Some(polarity))
|
||||
|
||||
// Clock port mapping
|
||||
/* Palmer: FIXME: I don't handle memories with read/write clocks yet. */
|
||||
/* Colin not all libPorts have clocks but all memPorts do*/
|
||||
libPort.src.clock.foreach { cPort =>
|
||||
stmts += connectPorts(WRef(memPort.src.clock.get.name),
|
||||
cPort.name,
|
||||
cPort.polarity) }
|
||||
stmts += connectPorts(WRef(memPort.src.clock.get.name), cPort.name, cPort.polarity)
|
||||
}
|
||||
|
||||
// Adress port mapping
|
||||
/* Palmer: The address port to a memory is just the low-order bits of
|
||||
* the top address. */
|
||||
stmts += connectPorts(WRef(memPort.src.address.name),
|
||||
libPort.src.address.name,
|
||||
libPort.src.address.polarity)
|
||||
stmts += connectPorts(WRef(memPort.src.address.name), libPort.src.address.name, libPort.src.address.polarity)
|
||||
|
||||
// Output port mapping
|
||||
(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,
|
||||
* there's nothing to do. */
|
||||
case (Some(PolarizedPort(mem, _)), None) =>
|
||||
System.err println "WARNING: Unable to match output ports on memory"
|
||||
System.err println s" outer output port: ${mem}"
|
||||
System.err.println("WARNING: Unable to match output ports on memory")
|
||||
System.err.println(s" outer output port: ${mem}")
|
||||
return None
|
||||
}
|
||||
|
||||
@@ -409,8 +431,8 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
|
||||
* port on the memory) then just don't worry about it,
|
||||
* there's nothing to do. */
|
||||
case (Some(PolarizedPort(mem, _)), None) =>
|
||||
System.err println "WARNING: Unable to match input ports on memory"
|
||||
System.err println s" outer input port: ${mem}"
|
||||
System.err.println("WARNING: Unable to match input ports on memory")
|
||||
System.err.println(s" outer input port: ${mem}")
|
||||
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.
|
||||
// The other case is if we're using a larger lib than mem.
|
||||
val usingLessThanLibMaskGran = (memPort.src.maskGran.get < libPort.src.effectiveMaskGran)
|
||||
val effectiveLibWidth = if (usingLessThanLibMaskGran)
|
||||
val effectiveLibWidth =
|
||||
if (usingLessThanLibMaskGran)
|
||||
memPort.src.maskGran.get
|
||||
else
|
||||
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 the memMaskGran is smaller than the lib's gran, then
|
||||
// zero out the upper bits.
|
||||
@@ -448,7 +474,10 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
|
||||
bits(WRef(mem), (low + i) / memPort.src.effectiveMaskGran)
|
||||
}
|
||||
}
|
||||
})).reverse)
|
||||
})
|
||||
)
|
||||
.reverse
|
||||
)
|
||||
}
|
||||
case None =>
|
||||
/* 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
|
||||
* the inner memory has availiable. */
|
||||
((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. */
|
||||
stmts += connectPorts(memMask, mask, mask_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) =>
|
||||
/* Palmer: If we don't have a chip enable but do have mask ports. */
|
||||
stmts += connectPorts(memMask, mask, mask_polarity)
|
||||
stmts += connectPorts(andAddrMatch(and(memWriteEnable, memChipEnable)),
|
||||
we, we_polarity)
|
||||
stmts += connectPorts(andAddrMatch(and(memWriteEnable, memChipEnable)), we, we_polarity)
|
||||
case (None, Some(PolarizedPort(we, we_polarity)), chipEnable) =>
|
||||
if (bitWidth(memMask.tpe) == 1) {
|
||||
/* 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. */
|
||||
chipEnable match {
|
||||
case Some(PolarizedPort(en, en_polarity)) => {
|
||||
stmts += connectPorts(andAddrMatch(and(memWriteEnable, memMask)),
|
||||
we, we_polarity)
|
||||
stmts += connectPorts(andAddrMatch(and(memWriteEnable, memMask)), we, we_polarity)
|
||||
stmts += connectPorts(andAddrMatch(memChipEnable), en, en_polarity)
|
||||
}
|
||||
case _ => {
|
||||
stmts += connectPorts(andAddrMatch(and(and(memWriteEnable, memChipEnable), memMask)),
|
||||
we, we_polarity)
|
||||
stmts += connectPorts(
|
||||
andAddrMatch(and(and(memWriteEnable, memChipEnable), memMask)),
|
||||
we,
|
||||
we_polarity
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -541,7 +575,7 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
|
||||
case Some(PolarizedPort(mem, _)) if cats.nonEmpty =>
|
||||
val name = s"${mem}_${i}"
|
||||
stmts += DefNode(NoInfo, name, cat(cats.toSeq.reverse))
|
||||
(outputs getOrElseUpdate (mem, ArrayBuffer[(Expression, Expression)]())) +=
|
||||
(outputs.getOrElseUpdate(mem, ArrayBuffer[(Expression, Expression)]())) +=
|
||||
(addrMatchReg -> WRef(name))
|
||||
case _ =>
|
||||
}
|
||||
@@ -549,12 +583,14 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
|
||||
}
|
||||
// Connect mem outputs
|
||||
val zeroOutputValue: Expression = UIntLiteral(0, IntWidth(mem.src.width))
|
||||
mem.src.ports foreach { port =>
|
||||
mem.src.ports.foreach { port =>
|
||||
port.output match {
|
||||
case Some(PolarizedPort(mem, _)) => outputs get mem match {
|
||||
case Some(PolarizedPort(mem, _)) =>
|
||||
outputs.get(mem) match {
|
||||
case Some(select) =>
|
||||
val output = (select foldRight (zeroOutputValue)) {
|
||||
case ((cond, tval), fval) => Mux(cond, tval, fval, fval.tpe) }
|
||||
val output = (select.foldRight(zeroOutputValue)) { case ((cond, tval), fval) =>
|
||||
Mux(cond, tval, fval, fval.tpe)
|
||||
}
|
||||
stmts += Connect(NoInfo, WRef(mem), output)
|
||||
case None =>
|
||||
}
|
||||
@@ -572,12 +608,11 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
|
||||
// Try to compile each of the memories in mems.
|
||||
// The 'state' is c.modules, which is a list of all the firrtl modules
|
||||
// in the 'circuit'.
|
||||
(mems foldLeft c.modules){ (modules, mem) =>
|
||||
|
||||
(mems.foldLeft(c.modules)) { (modules, mem) =>
|
||||
val sram = mem.src
|
||||
def groupMatchesMask(group: SRAMGroup, mem: SRAMMacro): Boolean = {
|
||||
val memMask = mem.ports map (_.maskGran) find (_.isDefined) map (_.get)
|
||||
val libMask = group.ports map (_.maskGran) find (_.isDefined) map (_.get)
|
||||
val memMask = mem.ports.map(_.maskGran).find(_.isDefined).map(_.get)
|
||||
val libMask = group.ports.map(_.maskGran).find(_.isDefined).map(_.get)
|
||||
(memMask, libMask) match {
|
||||
case (None, _) => true
|
||||
case (Some(_), None) => false
|
||||
@@ -587,9 +622,13 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
|
||||
// Add compiler memories that might map well to libs
|
||||
val compLibs = compilers match {
|
||||
case Some(SRAMCompiler(_, groups)) => {
|
||||
groups.filter(g => g.family == sram.family && groupMatchesMask(g, sram)).map( g => {
|
||||
for(w <- g.width; d <- g.depth if((sram.width % w == 0) && (sram.depth % d == 0)))
|
||||
yield Seq(new Macro(buildSRAMMacro(g, d, w, g.vt.head)))
|
||||
groups
|
||||
.filter(g => g.family == sram.family && groupMatchesMask(g, sram))
|
||||
.map(g => {
|
||||
for {
|
||||
w <- g.width
|
||||
d <- g.depth if ((sram.width % w == 0) && (sram.depth % d == 0))
|
||||
} yield Seq(new Macro(buildSRAMMacro(g, d, w, g.vt.head)))
|
||||
})
|
||||
}
|
||||
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
|
||||
// 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 =>
|
||||
/* Palmer: FIXME: This just assumes the Chisel and vendor ports are in the same
|
||||
* 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)
|
||||
case ((best, cost), lib) =>
|
||||
// Run the cost function to evaluate this potential compile.
|
||||
@@ -626,7 +665,9 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
|
||||
best match {
|
||||
case None => {
|
||||
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
|
||||
modules
|
||||
}
|
||||
@@ -642,7 +683,7 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
|
||||
}
|
||||
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
|
||||
@@ -657,13 +698,23 @@ class MacroCompilerTransform extends Transform {
|
||||
|
||||
def execute(state: CircuitState) = state.annotations.collect { case a: MacroCompilerAnnotation => a } match {
|
||||
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) {
|
||||
throw new UnsupportedOperationException("Not implemented yet")
|
||||
}
|
||||
|
||||
// Check that we don't have any modules both forced to compile and synflops.
|
||||
assert((forceCompile intersect forceSynflops).isEmpty, "Cannot have modules both forced to compile and synflops")
|
||||
assert((forceCompile.intersect(forceSynflops)).isEmpty, "Cannot have modules both forced to compile and synflops")
|
||||
|
||||
// Read, eliminate None, get only SRAM, make firrtl macro
|
||||
val mems: Option[Seq[Macro]] = (memFileFormat match {
|
||||
@@ -671,24 +722,22 @@ class MacroCompilerTransform extends Transform {
|
||||
case _ => mdf.macrolib.Utils.readMDFFromPath(Some(memFile))
|
||||
}) match {
|
||||
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
|
||||
}
|
||||
val libs: Option[Seq[Macro]] = mdf.macrolib.Utils.readMDFFromPath(libFile) match {
|
||||
case Some(x: Seq[mdf.macrolib.Macro]) =>
|
||||
Some(Utils.filterForSRAM(Some(x)) getOrElse(List()) map {new Macro(_)})
|
||||
Some(Utils.filterForSRAM(Some(x)).getOrElse(List()).map { new Macro(_) })
|
||||
case _ => None
|
||||
}
|
||||
val compilers: Option[mdf.macrolib.SRAMCompiler] = mdf.macrolib.Utils.readMDFFromPath(libFile) match {
|
||||
case Some(x: Seq[mdf.macrolib.Macro]) =>
|
||||
if (useCompiler) {
|
||||
findSRAMCompiler(Some(x))
|
||||
}
|
||||
else None
|
||||
} else None
|
||||
case _ => None
|
||||
}
|
||||
|
||||
|
||||
// Helper function to turn a set of mem names into a 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)
|
||||
@@ -706,12 +755,16 @@ class MacroCompilerTransform extends Transform {
|
||||
|
||||
val transforms = Seq(
|
||||
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
|
||||
} else {
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -729,7 +782,8 @@ class MacroCompilerOptimizations extends SeqTransform {
|
||||
new firrtl.transforms.ConstantPropagation,
|
||||
passes.Legalize,
|
||||
passes.SplitExpressions,
|
||||
passes.CommonSubexpressionElimination)
|
||||
passes.CommonSubexpressionElimination
|
||||
)
|
||||
}
|
||||
|
||||
class MacroCompiler extends Compiler {
|
||||
@@ -756,8 +810,9 @@ object MacroCompiler extends App {
|
||||
type MacroParamMap = Map[MacroParam, String]
|
||||
type CostParamMap = Map[String, String]
|
||||
type ForcedMemories = (Set[String], Set[String])
|
||||
val modeOptions: Seq[String] = MacroCompilerAnnotation.options
|
||||
.map { case (_, cmd, description) => s" $cmd: $description" }
|
||||
val modeOptions: Seq[String] = MacroCompilerAnnotation.options.map { case (_, cmd, description) =>
|
||||
s" $cmd: $description"
|
||||
}
|
||||
val usage: String = (Seq(
|
||||
"Options:",
|
||||
" -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-synflops [mem]: Force the given memory to be compiled via synflops regardless of the mode",
|
||||
" --mode:"
|
||||
) ++ modeOptions) mkString "\n"
|
||||
) ++ modeOptions).mkString("\n")
|
||||
|
||||
def parseArgs(map: MacroParamMap, costMap: CostParamMap, forcedMemories: ForcedMemories,
|
||||
args: List[String]): (MacroParamMap, CostParamMap, ForcedMemories) =
|
||||
def parseArgs(
|
||||
map: MacroParamMap,
|
||||
costMap: CostParamMap,
|
||||
forcedMemories: ForcedMemories,
|
||||
args: List[String]
|
||||
): (MacroParamMap, CostParamMap, ForcedMemories) =
|
||||
args match {
|
||||
case Nil => (map, costMap, forcedMemories)
|
||||
case ("-n" | "--macro-conf") :: value :: tail =>
|
||||
@@ -809,11 +868,17 @@ object MacroCompiler extends App {
|
||||
}
|
||||
|
||||
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 {
|
||||
val macros = params.get(MacrosFormat) match {
|
||||
case Some("conf") => 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)
|
||||
case Some("conf") =>
|
||||
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) {
|
||||
@@ -821,24 +886,28 @@ object MacroCompiler extends App {
|
||||
// determined as the firrtl "top-level module".
|
||||
val circuit = Circuit(NoInfo, macros, macros.last.name)
|
||||
val annotations = AnnotationSeq(
|
||||
Seq(MacroCompilerAnnotation(
|
||||
Seq(
|
||||
MacroCompilerAnnotation(
|
||||
circuit.main,
|
||||
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),
|
||||
CostMetric.getCostMetric(params.getOrElse(CostFunc, "default"), costParams),
|
||||
MacroCompilerAnnotation.stringToCompilerMode(params.getOrElse(Mode, "default")),
|
||||
params.contains(UseCompiler),
|
||||
forceCompile = forcedMemories._1, forceSynflops = forcedMemories._2
|
||||
forceCompile = forcedMemories._1,
|
||||
forceSynflops = forcedMemories._2
|
||||
)
|
||||
)
|
||||
)
|
||||
))
|
||||
)
|
||||
|
||||
// The actual MacroCompilerTransform basically just generates an input circuit
|
||||
val macroCompilerInput = CircuitState(circuit, MidForm, annotations)
|
||||
val macroCompiled = (new MacroCompilerTransform).execute(macroCompilerInput)
|
||||
|
||||
|
||||
// Since the MacroCompiler defines its own CLI, reconcile this with FIRRTL options
|
||||
val firOptions = new ExecutionOptionsManager("macrocompiler") with HasFirrtlOptions {
|
||||
firrtlOptions = FirrtlExecutionOptions(
|
||||
@@ -864,7 +933,7 @@ object MacroCompiler extends App {
|
||||
}
|
||||
} else {
|
||||
// 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
|
||||
params.get(Verilog) match {
|
||||
|
||||
@@ -10,8 +10,9 @@ import firrtl.passes.MemPortUtils.memPortField
|
||||
|
||||
class SynFlopsPass(synflops: Boolean, libs: Seq[Macro]) extends firrtl.passes.Pass {
|
||||
val extraMods = scala.collection.mutable.ArrayBuffer.empty[Module]
|
||||
lazy val libMods = (libs map { lib => lib.src.name -> {
|
||||
val (dataType, dataWidth) = (lib.src.ports foldLeft (None: Option[BigInt]))((res, port) =>
|
||||
lazy val libMods = (libs.map { lib =>
|
||||
lib.src.name -> {
|
||||
val (dataType, dataWidth) = (lib.src.ports.foldLeft(None: Option[BigInt]))((res, port) =>
|
||||
(res, port.maskPort) match {
|
||||
case (_, None) =>
|
||||
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
|
||||
// by changing its depth, and width
|
||||
val lib_macro = new Macro(lib.src.copy(name="split_"+lib.src.name,
|
||||
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 lib_macro = new Macro(
|
||||
lib.src.copy(
|
||||
name = "split_" + lib.src.name,
|
||||
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 (real_mod, real_macro) = mod_macro.get
|
||||
|
||||
@@ -45,18 +56,17 @@ class SynFlopsPass(synflops: Boolean, libs: Seq[Macro]) extends firrtl.passes.Pa
|
||||
maxDepth,
|
||||
1, // writeLatency
|
||||
1, // readLatency. This is possible because of VerilogMemDelays
|
||||
real_macro.readers.indices map (i => s"R_$i"),
|
||||
real_macro.writers.indices map (i => s"W_$i"),
|
||||
real_macro.readwriters.indices map (i => s"RW_$i")
|
||||
real_macro.readers.indices.map(i => s"R_$i"),
|
||||
real_macro.writers.indices.map(i => s"W_$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 address = portToExpression(r.src.address)
|
||||
val enable = (r.src chipEnable, r.src readEnable) match {
|
||||
case (Some(en_port), Some(re_port)) =>
|
||||
and(portToExpression(en_port),
|
||||
portToExpression(re_port))
|
||||
and(portToExpression(en_port), portToExpression(re_port))
|
||||
case (Some(en_port), None) => portToExpression(en_port)
|
||||
case (None, Some(re_port)) => portToExpression(re_port)
|
||||
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 address = portToExpression(w.src.address)
|
||||
val enable = (w.src.chipEnable, w.src.writeEnable) match {
|
||||
case (Some(en), Some(we)) =>
|
||||
and(portToExpression(en),
|
||||
portToExpression(we))
|
||||
and(portToExpression(en), portToExpression(we))
|
||||
case (Some(en), None) => portToExpression(en)
|
||||
case (None, Some(we)) => portToExpression(we)
|
||||
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 address = portToExpression(rw.src.address)
|
||||
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))))
|
||||
real_mod
|
||||
}}).toMap
|
||||
}
|
||||
}).toMap
|
||||
|
||||
def run(c: Circuit): Circuit = {
|
||||
if (!synflops) c
|
||||
else c.copy(modules = (c.modules map (m => libMods.getOrElse(m.name, m))) ++ extraMods)
|
||||
else c.copy(modules = (c.modules.map(m => libMods.getOrElse(m.name, m))) ++ extraMods)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,37 +21,46 @@ class FirrtlMacroPort(port: MacroPort) {
|
||||
val isWriter = port.input.nonEmpty && port.output.isEmpty
|
||||
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 maskType = UIntType(IntWidth(port.width.get / port.effectiveMaskGran))
|
||||
|
||||
// Bundle representing this macro port.
|
||||
val tpe = BundleType(Seq(
|
||||
Field(port.address.name, Flip, addrType)) ++
|
||||
(port.clock map (p => Field(p.name, Flip, ClockType))) ++
|
||||
(port.input map (p => Field(p.name, Flip, dataType))) ++
|
||||
(port.output map (p => Field(p.name, Default, dataType))) ++
|
||||
(port.chipEnable map (p => Field(p.name, Flip, BoolType))) ++
|
||||
(port.readEnable map (p => Field(p.name, Flip, BoolType))) ++
|
||||
(port.writeEnable map (p => Field(p.name, Flip, BoolType))) ++
|
||||
(port.maskPort map (p => Field(p.name, Flip, maskType)))
|
||||
val tpe = BundleType(
|
||||
Seq(Field(port.address.name, Flip, addrType)) ++
|
||||
(port.clock.map(p => Field(p.name, Flip, ClockType))) ++
|
||||
(port.input.map(p => Field(p.name, Flip, dataType))) ++
|
||||
(port.output.map(p => Field(p.name, Default, dataType))) ++
|
||||
(port.chipEnable.map(p => Field(p.name, Flip, BoolType))) ++
|
||||
(port.readEnable.map(p => Field(p.name, Flip, BoolType))) ++
|
||||
(port.writeEnable.map(p => Field(p.name, Flip, BoolType))) ++
|
||||
(port.maskPort.map(p => Field(p.name, Flip, maskType)))
|
||||
)
|
||||
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.
|
||||
class Macro(srcMacro: SRAMMacro) {
|
||||
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 readers = firrtlPorts filter (p => p.isReader)
|
||||
val readwriters = firrtlPorts filter (p => p.isReadWriter)
|
||||
val writers = firrtlPorts.filter(p => p.isWriter)
|
||||
val readers = firrtlPorts.filter(p => p.isReader)
|
||||
val readwriters = firrtlPorts.filter(p => p.isReadWriter)
|
||||
|
||||
val sortedPorts = writers ++ readers ++ readwriters
|
||||
val extraPorts = srcMacro.extraPorts map { p =>
|
||||
val extraPorts = srcMacro.extraPorts.map { p =>
|
||||
assert(p.portType == Constant) // TODO: release it?
|
||||
val name = p.name
|
||||
val width = BigInt(p.width.toLong)
|
||||
@@ -60,10 +69,10 @@ class Macro(srcMacro: SRAMMacro) {
|
||||
}
|
||||
|
||||
// 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)) ++
|
||||
(extraPorts map { case (name, value) => Port(NoInfo, name, Input, value.tpe) })
|
||||
private val modPorts = (firrtlPorts.flatMap(_.ports)) ++
|
||||
(extraPorts.map { case (name, value) => Port(NoInfo, name, Input, value.tpe) })
|
||||
val blackbox = ExtModule(NoInfo, srcMacro.name, modPorts, srcMacro.name, Nil)
|
||||
def module(body: Statement) = Module(NoInfo, srcMacro.name, modPorts, body)
|
||||
}
|
||||
@@ -71,7 +80,8 @@ class Macro(srcMacro: SRAMMacro) {
|
||||
object Utils {
|
||||
def filterForSRAM(s: Option[Seq[mdf.macrolib.Macro]]): Option[Seq[mdf.macrolib.SRAMMacro]] = {
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -81,8 +91,14 @@ object Utils {
|
||||
}
|
||||
def readConfFromString(str: String): Seq[mdf.macrolib.Macro] = {
|
||||
MemConf.fromString(str).map { m: MemConf =>
|
||||
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))
|
||||
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)
|
||||
)
|
||||
}
|
||||
}
|
||||
def portSpecToFamily(ports: Seq[MemPort]): String = {
|
||||
@@ -99,56 +115,66 @@ object Utils {
|
||||
var numR = 0
|
||||
var numW = 0
|
||||
var numRW = 0
|
||||
ports.map { _ match {
|
||||
ports.map {
|
||||
_ match {
|
||||
case ReadPort => {
|
||||
val portName = s"R${numR}"
|
||||
numR += 1
|
||||
MacroPort(
|
||||
width=Some(width), depth=Some(depth),
|
||||
width = Some(width),
|
||||
depth = Some(depth),
|
||||
address = PolarizedPort(s"${portName}_addr", ActiveHigh),
|
||||
clock = Some(PolarizedPort(s"${portName}_clk", PositiveEdge)),
|
||||
readEnable = Some(PolarizedPort(s"${portName}_en", ActiveHigh)),
|
||||
output = Some(PolarizedPort(s"${portName}_data", ActiveHigh))
|
||||
) }
|
||||
)
|
||||
}
|
||||
case WritePort => {
|
||||
val portName = s"W${numW}"
|
||||
numW += 1
|
||||
MacroPort(
|
||||
width=Some(width), depth=Some(depth),
|
||||
width = Some(width),
|
||||
depth = Some(depth),
|
||||
address = PolarizedPort(s"${portName}_addr", ActiveHigh),
|
||||
clock = Some(PolarizedPort(s"${portName}_clk", PositiveEdge)),
|
||||
writeEnable = Some(PolarizedPort(s"${portName}_en", ActiveHigh)),
|
||||
input = Some(PolarizedPort(s"${portName}_data", ActiveHigh))
|
||||
) }
|
||||
)
|
||||
}
|
||||
case MaskedWritePort => {
|
||||
val portName = s"W${numW}"
|
||||
numW += 1
|
||||
MacroPort(
|
||||
width=Some(width), depth=Some(depth),
|
||||
width = Some(width),
|
||||
depth = Some(depth),
|
||||
address = PolarizedPort(s"${portName}_addr", ActiveHigh),
|
||||
clock = Some(PolarizedPort(s"${portName}_clk", PositiveEdge)),
|
||||
writeEnable = Some(PolarizedPort(s"${portName}_en", ActiveHigh)),
|
||||
maskPort = Some(PolarizedPort(s"${portName}_mask", ActiveHigh)),
|
||||
maskGran = maskGran,
|
||||
input = Some(PolarizedPort(s"${portName}_data", ActiveHigh))
|
||||
) }
|
||||
)
|
||||
}
|
||||
case ReadWritePort => {
|
||||
val portName = s"RW${numRW}"
|
||||
numRW += 1
|
||||
MacroPort(
|
||||
width=Some(width), depth=Some(depth),
|
||||
width = Some(width),
|
||||
depth = Some(depth),
|
||||
address = PolarizedPort(s"${portName}_addr", ActiveHigh),
|
||||
clock = Some(PolarizedPort(s"${portName}_clk", PositiveEdge)),
|
||||
chipEnable = Some(PolarizedPort(s"${portName}_en", ActiveHigh)),
|
||||
writeEnable = Some(PolarizedPort(s"${portName}_wmode", ActiveHigh)),
|
||||
input = Some(PolarizedPort(s"${portName}_wdata", ActiveHigh)),
|
||||
output = Some(PolarizedPort(s"${portName}_rdata", ActiveHigh))
|
||||
) }
|
||||
)
|
||||
}
|
||||
case MaskedReadWritePort => {
|
||||
val portName = s"RW${numRW}"
|
||||
numRW += 1
|
||||
MacroPort(
|
||||
width=Some(width), depth=Some(depth),
|
||||
width = Some(width),
|
||||
depth = Some(depth),
|
||||
address = PolarizedPort(s"${portName}_addr", ActiveHigh),
|
||||
clock = Some(PolarizedPort(s"${portName}_clk", PositiveEdge)),
|
||||
chipEnable = Some(PolarizedPort(s"${portName}_en", ActiveHigh)),
|
||||
@@ -157,24 +183,48 @@ object Utils {
|
||||
maskGran = maskGran,
|
||||
input = Some(PolarizedPort(s"${portName}_wdata", ActiveHigh)),
|
||||
output = Some(PolarizedPort(s"${portName}_rdata", ActiveHigh))
|
||||
) }
|
||||
}}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
def findSRAMCompiler(s: Option[Seq[mdf.macrolib.Macro]]): Option[mdf.macrolib.SRAMCompiler] = {
|
||||
s match {
|
||||
case Some(l: Seq[mdf.macrolib.Macro]) =>
|
||||
l collectFirst {
|
||||
case x: mdf.macrolib.SRAMCompiler => x
|
||||
l.collectFirst { case x: mdf.macrolib.SRAMCompiler =>
|
||||
x
|
||||
}
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
def buildSRAMMacros(s: mdf.macrolib.SRAMCompiler): Seq[mdf.macrolib.SRAMMacro] = {
|
||||
for (g <- s.groups; d <- g.depth; w <- g.width; vt <- g.vt)
|
||||
yield mdf.macrolib.SRAMMacro(makeName(g, d, w, vt), w, d, g.family, g.ports.map(_.copy(width=Some(w), depth=Some(d))), vt, g.mux, g.extraPorts)
|
||||
for {
|
||||
g <- s.groups
|
||||
d <- g.depth
|
||||
w <- g.width
|
||||
vt <- g.vt
|
||||
} yield mdf.macrolib.SRAMMacro(
|
||||
makeName(g, d, w, vt),
|
||||
w,
|
||||
d,
|
||||
g.family,
|
||||
g.ports.map(_.copy(width = Some(w), depth = Some(d))),
|
||||
vt,
|
||||
g.mux,
|
||||
g.extraPorts
|
||||
)
|
||||
}
|
||||
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 = {
|
||||
g.name.foldLeft("") { (builder, next) =>
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
"depth": "512",
|
||||
"mux": 4,
|
||||
"family": "1rw",
|
||||
"ports" : [ {
|
||||
"ports": [
|
||||
{
|
||||
"address port name": "addr",
|
||||
"address port polarity": "active high",
|
||||
"clock port name": "clk",
|
||||
@@ -22,6 +23,7 @@
|
||||
"mask port name": "mport",
|
||||
"mask port polarity": "active low",
|
||||
"mask granularity": 1
|
||||
} ]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
"depth": "4096",
|
||||
"mux": 4,
|
||||
"family": "1rw",
|
||||
"ports" : [ {
|
||||
"ports": [
|
||||
{
|
||||
"address port name": "addr",
|
||||
"address port polarity": "active high",
|
||||
"clock port name": "clk",
|
||||
@@ -19,6 +20,7 @@
|
||||
"output port polarity": "active high",
|
||||
"input port name": "datain",
|
||||
"input port polarity": "active high"
|
||||
} ]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -4,8 +4,7 @@ import mdf.macrolib._
|
||||
|
||||
/** 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.
|
||||
*/
|
||||
object TestMinWidthMetric extends CostMetric with CostMetricCompanion {
|
||||
|
||||
@@ -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) =
|
||||
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 ++
|
||||
(if (synflops) List("--mode", "synflops") 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.
|
||||
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)
|
||||
val result = execute(mem, lib, synflops, useCompiler)
|
||||
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").
|
||||
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)
|
||||
}
|
||||
|
||||
// Execute the macro compiler and returns a Circuit containing the output of
|
||||
// the memory compiler.
|
||||
def execute(memFile: Option[String], libFile: Option[String], synflops: Boolean): Circuit = execute(memFile, libFile, synflops, false)
|
||||
def execute(memFile: Option[String], libFile: Option[String], synflops: Boolean): Circuit =
|
||||
execute(memFile, libFile, synflops, false)
|
||||
def execute(memFile: Option[String], libFile: Option[String], synflops: Boolean, useCompiler: Boolean): Circuit = {
|
||||
var mem_full = concat(memPrefix, memFile)
|
||||
var lib_full = concat(libPrefix, libFile)
|
||||
|
||||
require(memFile.isDefined)
|
||||
val mems: Seq[Macro] = Utils.filterForSRAM(mdf.macrolib.Utils.readMDFFromPath(mem_full)).get map (new Macro(_))
|
||||
val mems: Seq[Macro] = Utils.filterForSRAM(mdf.macrolib.Utils.readMDFFromPath(mem_full)).get.map(new Macro(_))
|
||||
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 {
|
||||
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
|
||||
}
|
||||
}
|
||||
val macros = mems map (_.blackbox)
|
||||
val macros = mems.map(_.blackbox)
|
||||
val circuit = Circuit(NoInfo, macros, macros.last.name)
|
||||
val passes = Seq(
|
||||
new MacroCompilerPass(Some(mems), libs, 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)
|
||||
new MacroCompilerPass(
|
||||
Some(mems),
|
||||
libs,
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
// Helper method to deal with String + Option[String]
|
||||
private def concat(a: String, b: String): String = { a + "/" + b }
|
||||
private def concat(a: String, b: Option[String]): Option[String] = {
|
||||
@@ -126,7 +146,6 @@ trait HasSRAMGenerator {
|
||||
implicit def Int2SomeInt(i: Int): Option[Int] = Some(i)
|
||||
implicit def BigInt2SomeBigInt(i: BigInt): Option[BigInt] = Some(i)
|
||||
|
||||
|
||||
// Generate a standard (read/write/combo) port for testing.
|
||||
// Helper methods for optional width argument
|
||||
def generateTestPort(
|
||||
@@ -144,44 +163,70 @@ trait HasSRAMGenerator {
|
||||
MacroPort(
|
||||
address = PolarizedPort(name = realPrefix + "addr", polarity = ActiveHigh),
|
||||
clock = Some(PolarizedPort(name = realPrefix + "clk", polarity = PositiveEdge)),
|
||||
|
||||
readEnable = if (readEnable) Some(PolarizedPort(name = realPrefix + "read_en", polarity = ActiveHigh)) else None,
|
||||
writeEnable = if (writeEnable) Some(PolarizedPort(name = realPrefix + "write_en", polarity = ActiveHigh)) else None,
|
||||
|
||||
writeEnable =
|
||||
if (writeEnable) Some(PolarizedPort(name = realPrefix + "write_en", polarity = ActiveHigh)) else None,
|
||||
output = if (read) Some(PolarizedPort(name = realPrefix + "dout", polarity = ActiveHigh)) else None,
|
||||
input = if (write) Some(PolarizedPort(name = realPrefix + "din", polarity = ActiveHigh)) else None,
|
||||
|
||||
maskPort = maskGran match {
|
||||
case Some(x: Int) => Some(PolarizedPort(name = realPrefix + "mask", polarity = ActiveHigh))
|
||||
case _ => None
|
||||
},
|
||||
maskGran = maskGran,
|
||||
|
||||
width = width, depth = depth // These numbers don't matter here.
|
||||
width = width,
|
||||
depth = depth // These numbers don't matter here.
|
||||
)
|
||||
}
|
||||
|
||||
// Generate a read port for testing.
|
||||
def generateReadPort(prefix: String, width: 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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(
|
||||
prefix, width, depth, maskGran = maskGran,
|
||||
write = true, writeEnable = true,
|
||||
read = true, readEnable = false
|
||||
prefix,
|
||||
width,
|
||||
depth,
|
||||
maskGran = maskGran,
|
||||
write = true,
|
||||
writeEnable = true,
|
||||
read = true,
|
||||
readEnable = false
|
||||
)
|
||||
}
|
||||
|
||||
// Generate a "simple" SRAM (active high/positive edge, 1 read-write port).
|
||||
def generateSRAM(name: String, prefix: String, width: Int, depth: 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(
|
||||
name = name,
|
||||
width = width,
|
||||
@@ -193,17 +238,35 @@ trait HasSRAMGenerator {
|
||||
}
|
||||
|
||||
// Generate a "simple" SRAM group (active high/positive edge, 1 read-write port).
|
||||
def generateSimpleSRAMGroup(prefix: String, mux: Int, depth: Range, width: Range, maskGran: Option[Int] = None, extraPorts: Seq[MacroExtraPort] = List()): SRAMGroup = {
|
||||
SRAMGroup(Seq("mygroup_", "width", "x", "depth", "_", "VT"), "1rw", Seq("svt", "lvt", "ulvt"), mux, depth, width, Seq(generateReadWritePort(prefix, None, None, maskGran)))
|
||||
def generateSimpleSRAMGroup(
|
||||
prefix: String,
|
||||
mux: Int,
|
||||
depth: Range,
|
||||
width: Range,
|
||||
maskGran: Option[Int] = None,
|
||||
extraPorts: Seq[MacroExtraPort] = List()
|
||||
): SRAMGroup = {
|
||||
SRAMGroup(
|
||||
Seq("mygroup_", "width", "x", "depth", "_", "VT"),
|
||||
"1rw",
|
||||
Seq("svt", "lvt", "ulvt"),
|
||||
mux,
|
||||
depth,
|
||||
width,
|
||||
Seq(generateReadWritePort(prefix, None, None, maskGran))
|
||||
)
|
||||
}
|
||||
|
||||
// 'vt': ('svt','lvt','ulvt'), 'mux': 2, 'depth': range(16,513,8), 'width': range(8,289,2), 'ports': 1
|
||||
// 'vt': ('svt','lvt','ulvt'), 'mux': 4, 'depth': range(32,1025,16), 'width': range(4,145), 'ports': 1}
|
||||
def generateSRAMCompiler(name: String, prefix: String): mdf.macrolib.SRAMCompiler = {
|
||||
SRAMCompiler(name, Seq(
|
||||
SRAMCompiler(
|
||||
name,
|
||||
Seq(
|
||||
generateSimpleSRAMGroup(prefix, 2, Range(16, 512, 8), Range(8, 288, 2)),
|
||||
generateSimpleSRAMGroup(prefix, 4, Range(32, 1024, 16), Range(4, 144, 1))
|
||||
))
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,8 +351,7 @@ trait HasSimpleTestGenerator {
|
||||
lazy val lastWidthBits = if (memWidth % usableLibWidth == 0) usableLibWidth else (memWidth % usableLibWidth)
|
||||
lazy val selectBits = mem_addr_width - lib_addr_width
|
||||
|
||||
/**
|
||||
* Convenience function to generate a mask statement.
|
||||
/** Convenience function to generate a mask statement.
|
||||
* @param widthInst Width instance (mem_0_x)
|
||||
* @param depthInst Depth instance (mem_x_0)
|
||||
*/
|
||||
@@ -312,7 +374,7 @@ trait HasSimpleTestGenerator {
|
||||
// calculateMaskBit({0, 1}) = 0 and calculateMaskBit({1, 2}) = 1
|
||||
def calculateMaskBit(bit: Int): Int = bit / memMaskGran.getOrElse(memWidth)
|
||||
|
||||
val bitsArr = ((libMaskBits - 1 to 0 by -1) map (x => {
|
||||
val bitsArr = ((libMaskBits - 1 to 0 by -1).map(x => {
|
||||
if (x * libMaskGran.get > myMemWidth) {
|
||||
// If we have extra mask bits leftover after the effective width,
|
||||
// disable those bits.
|
||||
@@ -340,7 +402,17 @@ trait HasSimpleTestGenerator {
|
||||
* @param mask Mask granularity (# bits) of the port or None.
|
||||
* @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 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 readEnable Has a read enable port?
|
||||
* @param mask Mask granularity (# bits) of the port or None.
|
||||
* @param extraPorts Extra ports (name, # bits)
|
||||
*/
|
||||
def generateReadWriteFooterPort(prefix: String, 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)
|
||||
def generateReadWriteFooterPort(
|
||||
prefix: String,
|
||||
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.
|
||||
* @param prefix Memory port prefix (e.g. "x" for ports like "x_clk")
|
||||
* @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 = {
|
||||
generatePort(prefix, mem_addr_width, memWidth,
|
||||
write=true, writeEnable=true, read=true, readEnable=readEnable, mask)
|
||||
generatePort(
|
||||
prefix,
|
||||
mem_addr_width,
|
||||
memWidth,
|
||||
write = true,
|
||||
writeEnable = true,
|
||||
read = true,
|
||||
readEnable = readEnable,
|
||||
mask
|
||||
)
|
||||
}
|
||||
|
||||
// Generate the header memory ports.
|
||||
def generateHeaderPorts(): String = {
|
||||
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
|
||||
@@ -405,8 +503,12 @@ ${generateHeaderPorts}
|
||||
// Generate the target memory ports.
|
||||
def generateFooterPorts(): String = {
|
||||
require(libSRAM.ports.size == 1, "Footer generator only supports single RW port mem")
|
||||
generateReadWriteFooterPort(libPortPrefix, libSRAM.ports(0).readEnable.isDefined,
|
||||
if (libHasMask) Some(libMaskBits) else None, extraPorts.map(p => (p.name, p.width)))
|
||||
generateReadWriteFooterPort(
|
||||
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).
|
||||
@@ -450,4 +552,3 @@ trait HasNoLibTestGenerator extends HasSimpleTestGenerator {
|
||||
// If there is no lib, don't generate a body.
|
||||
override def generateBody = ""
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,7 @@ trait MasksTestSettings {
|
||||
}
|
||||
|
||||
// Try all four different kinds of mask config:
|
||||
/**
|
||||
*
|
||||
* Non-masked mem Masked mem
|
||||
/** Non-masked mem Masked mem
|
||||
* ---------------------------------
|
||||
* 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 memWidth = 32
|
||||
override lazy val memMaskGran = None
|
||||
@@ -29,7 +30,10 @@ class Masks_FourTypes_NonMaskedMem_NonMaskedLib extends MacroCompilerSpec with H
|
||||
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 memWidth = 32
|
||||
override lazy val memMaskGran = None
|
||||
@@ -39,7 +43,10 @@ class Masks_FourTypes_NonMaskedMem_MaskedLib extends MacroCompilerSpec with HasS
|
||||
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 memWidth = 32
|
||||
override lazy val memMaskGran = Some(8)
|
||||
@@ -49,7 +56,10 @@ class Masks_FourTypes_MaskedMem_NonMaskedLib extends MacroCompilerSpec with HasS
|
||||
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 memWidth = 32
|
||||
override lazy val memMaskGran = Some(4)
|
||||
@@ -59,7 +69,10 @@ class Masks_FourTypes_MaskedMem_NonMaskedLib_SmallerMaskGran extends MacroCompil
|
||||
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 memWidth = 32
|
||||
override lazy val memMaskGran = Some(8)
|
||||
@@ -69,7 +82,10 @@ class Masks_FourTypes_MaskedMem_MaskedLib extends MacroCompilerSpec with HasSRAM
|
||||
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 memWidth = 32
|
||||
override lazy val memMaskGran = Some(8)
|
||||
@@ -79,7 +95,10 @@ class Masks_FourTypes_MaskedMem_MaskedLib_SameMaskGran extends MacroCompilerSpec
|
||||
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 memWidth = 64
|
||||
override lazy val memMaskGran = Some(4)
|
||||
@@ -103,7 +122,11 @@ class Masks_BitMaskedMem_NonMaskedLib extends MacroCompilerSpec with HasSRAMGene
|
||||
|
||||
// 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 memMaskGran = Some(32)
|
||||
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.
|
||||
|
||||
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 memMaskGran = Some(8)
|
||||
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)
|
||||
}
|
||||
|
||||
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 memMaskGran = Some(16)
|
||||
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)
|
||||
}
|
||||
|
||||
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 memMaskGran = Some(32)
|
||||
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)
|
||||
}
|
||||
|
||||
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 memMaskGran = Some(64)
|
||||
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.
|
||||
|
||||
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 memMaskGran = Some(32)
|
||||
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)
|
||||
}
|
||||
|
||||
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 memMaskGran = Some(32)
|
||||
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)
|
||||
}
|
||||
|
||||
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 memMaskGran = 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
|
||||
|
||||
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 memMaskGran = Some(10)
|
||||
override lazy val libMaskGran = Some(1)
|
||||
@@ -181,16 +236,24 @@ class Masks_IntegerMaskMultiple_20_10 extends MacroCompilerSpec with HasSRAMGene
|
||||
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 memMaskGran = Some(21)
|
||||
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)
|
||||
}
|
||||
|
||||
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 memMaskGran = Some(21)
|
||||
override lazy val libMaskGran = Some(1)
|
||||
@@ -198,7 +261,11 @@ class Masks_IntegerMaskMultiple_21_21 extends MacroCompilerSpec with HasSRAMGene
|
||||
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 memMaskGran = Some(21)
|
||||
override lazy val libMaskGran = Some(1)
|
||||
@@ -206,7 +273,11 @@ class Masks_IntegerMaskMultiple_84_21 extends MacroCompilerSpec with HasSRAMGene
|
||||
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 memMaskGran = Some(23)
|
||||
override lazy val libMaskGran = Some(1)
|
||||
@@ -214,7 +285,11 @@ class Masks_IntegerMaskMultiple_92_23 extends MacroCompilerSpec with HasSRAMGene
|
||||
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 memMaskGran = Some(13)
|
||||
override lazy val libMaskGran = Some(1)
|
||||
@@ -222,7 +297,11 @@ class Masks_IntegerMaskMultiple_117_13 extends MacroCompilerSpec with HasSRAMGen
|
||||
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 memMaskGran = Some(20)
|
||||
override lazy val libMaskGran = Some(1)
|
||||
@@ -230,7 +309,11 @@ class Masks_IntegerMaskMultiple_160_20 extends MacroCompilerSpec with HasSRAMGen
|
||||
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 memMaskGran = Some(23)
|
||||
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
|
||||
|
||||
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 memMaskGran = Some(3)
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -17,15 +17,28 @@ class SplitWidth_2rw extends MacroCompilerSpec with HasSRAMGenerator with HasSim
|
||||
width = memWidth,
|
||||
depth = memDepth,
|
||||
family = "2rw",
|
||||
ports=Seq(generateTestPort(
|
||||
"portA", memWidth, Some(memDepth), maskGran=memMaskGran,
|
||||
write=true, writeEnable=true,
|
||||
read=true, readEnable=true
|
||||
), generateTestPort(
|
||||
"portB", memWidth, Some(memDepth), maskGran=memMaskGran,
|
||||
write=true, writeEnable=true,
|
||||
read=true, readEnable=true
|
||||
))
|
||||
ports = Seq(
|
||||
generateTestPort(
|
||||
"portA",
|
||||
memWidth,
|
||||
Some(memDepth),
|
||||
maskGran = memMaskGran,
|
||||
write = 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,
|
||||
depth = libDepth,
|
||||
family = "2rw",
|
||||
ports=Seq(generateTestPort(
|
||||
"portA", libWidth, libDepth,
|
||||
write=true, writeEnable=true,
|
||||
read=true, readEnable=true
|
||||
), generateTestPort(
|
||||
"portB", libWidth, libDepth,
|
||||
write=true, writeEnable=true,
|
||||
read=true, readEnable=true
|
||||
))
|
||||
ports = Seq(
|
||||
generateTestPort(
|
||||
"portA",
|
||||
libWidth,
|
||||
libDepth,
|
||||
write = true,
|
||||
writeEnable = true,
|
||||
read = true,
|
||||
readEnable = true
|
||||
),
|
||||
generateTestPort(
|
||||
"portB",
|
||||
libWidth,
|
||||
libDepth,
|
||||
write = true,
|
||||
writeEnable = true,
|
||||
read = true,
|
||||
readEnable = true
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
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() = {
|
||||
@@ -132,15 +160,28 @@ class SplitWidth_1r_1w extends MacroCompilerSpec with HasSRAMGenerator with HasS
|
||||
width = memWidth,
|
||||
depth = memDepth,
|
||||
family = "1r1w",
|
||||
ports=Seq(generateTestPort(
|
||||
"portA", memWidth, Some(memDepth), maskGran=memMaskGran,
|
||||
write=false, writeEnable=false,
|
||||
read=true, readEnable=true
|
||||
), generateTestPort(
|
||||
"portB", memWidth, Some(memDepth), maskGran=memMaskGran,
|
||||
write=true, writeEnable=true,
|
||||
read=false, readEnable=false
|
||||
))
|
||||
ports = Seq(
|
||||
generateTestPort(
|
||||
"portA",
|
||||
memWidth,
|
||||
Some(memDepth),
|
||||
maskGran = memMaskGran,
|
||||
write = 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,
|
||||
depth = libDepth,
|
||||
family = "1r1w",
|
||||
ports=Seq(generateTestPort(
|
||||
"portA", libWidth, libDepth,
|
||||
write=false, writeEnable=false,
|
||||
read=true, readEnable=true
|
||||
), generateTestPort(
|
||||
"portB", libWidth, libDepth,
|
||||
write=true, writeEnable=true,
|
||||
read=false, readEnable=false
|
||||
))
|
||||
ports = Seq(
|
||||
generateTestPort(
|
||||
"portA",
|
||||
libWidth,
|
||||
libDepth,
|
||||
write = false,
|
||||
writeEnable = false,
|
||||
read = true,
|
||||
readEnable = true
|
||||
),
|
||||
generateTestPort(
|
||||
"portB",
|
||||
libWidth,
|
||||
libDepth,
|
||||
write = true,
|
||||
writeEnable = true,
|
||||
read = false,
|
||||
readEnable = false
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override def generateHeaderPorts() = {
|
||||
generatePort("portA", mem_addr_width, 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))
|
||||
generatePort(
|
||||
"portA",
|
||||
mem_addr_width,
|
||||
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() = {
|
||||
generatePort("portA", lib_addr_width, 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)
|
||||
generatePort(
|
||||
"portA",
|
||||
lib_addr_width,
|
||||
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() =
|
||||
@@ -238,15 +322,28 @@ class SplitWidth_2rw_differentMasks extends MacroCompilerSpec with HasSRAMGenera
|
||||
width = memWidth,
|
||||
depth = memDepth,
|
||||
family = "2rw",
|
||||
ports=Seq(generateTestPort(
|
||||
"portA", memWidth, Some(memDepth), maskGran=memMaskGran,
|
||||
write=true, writeEnable=true,
|
||||
read=true, readEnable=true
|
||||
), generateTestPort(
|
||||
"portB", memWidth, Some(memDepth), maskGran=Some(memMaskGranB),
|
||||
write=true, writeEnable=true,
|
||||
read=true, readEnable=true
|
||||
))
|
||||
ports = Seq(
|
||||
generateTestPort(
|
||||
"portA",
|
||||
memWidth,
|
||||
Some(memDepth),
|
||||
maskGran = memMaskGran,
|
||||
write = 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,
|
||||
depth = libDepth,
|
||||
family = "2rw",
|
||||
ports=Seq(generateTestPort(
|
||||
"portA", libWidth, libDepth,
|
||||
write=true, writeEnable=true,
|
||||
read=true, readEnable=true
|
||||
), generateTestPort(
|
||||
"portB", libWidth, libDepth,
|
||||
write=true, writeEnable=true,
|
||||
read=true, readEnable=true
|
||||
))
|
||||
ports = Seq(
|
||||
generateTestPort(
|
||||
"portA",
|
||||
libWidth,
|
||||
libDepth,
|
||||
write = true,
|
||||
writeEnable = true,
|
||||
read = true,
|
||||
readEnable = true
|
||||
),
|
||||
generateTestPort(
|
||||
"portB",
|
||||
libWidth,
|
||||
libDepth,
|
||||
write = true,
|
||||
writeEnable = true,
|
||||
read = true,
|
||||
readEnable = true
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
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() = {
|
||||
|
||||
@@ -13,7 +13,6 @@ class SRAMCompiler extends MacroCompilerSpec with HasSRAMGenerator with HasSimpl
|
||||
|
||||
writeToLib(lib, Seq(compiler))
|
||||
|
||||
|
||||
writeToMem(mem, Seq(generateSRAM("mymem", "X", 8, 16)))
|
||||
|
||||
compileExecuteAndTest(mem, Some(lib), verilog, output = output, false, true)
|
||||
|
||||
@@ -28,9 +28,12 @@ s"""
|
||||
|
||||
for (i <- 0 to depthInstances - 1) {
|
||||
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 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(
|
||||
s"""
|
||||
inst mem_${i}_0 of ${lib_name}
|
||||
@@ -49,15 +52,18 @@ s"""
|
||||
s"""UInt<${libWidth}>("h0")"""
|
||||
} else {
|
||||
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) {
|
||||
output append generate_outer_dout_tree(0, depthInstances)
|
||||
output.append(generate_outer_dout_tree(0, depthInstances))
|
||||
} else {
|
||||
output append s"""mux(UInt<1>("h1"), ${memPortPrefix}_dout_0, UInt<${libWidth}>("h0"))"""
|
||||
output.append(s"""mux(UInt<1>("h1"), ${memPortPrefix}_dout_0, UInt<${libWidth}>("h0"))""")
|
||||
}
|
||||
|
||||
output.toString
|
||||
@@ -154,7 +160,10 @@ class SplitDepth2048x8_mrw_lib8 extends MacroCompilerSpec with HasSRAMGenerator
|
||||
}
|
||||
|
||||
// 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 memDepth = BigInt(2048)
|
||||
override lazy val libDepth = BigInt(1024)
|
||||
@@ -165,7 +174,10 @@ class SplitDepth2048x64_mrw_mem32_lib8 extends MacroCompilerSpec with HasSRAMGen
|
||||
}
|
||||
|
||||
// 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 memDepth = BigInt(2048)
|
||||
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 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)
|
||||
}
|
||||
|
||||
@@ -224,7 +236,7 @@ class SplitDepth2048x32_mrw_mem7_lib1 extends MacroCompilerSpec with HasSRAMGene
|
||||
override lazy val memMaskGran = Some(7)
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -235,7 +247,7 @@ class SplitDepth2048x32_mrw_mem9_lib1 extends MacroCompilerSpec with HasSRAMGene
|
||||
override lazy val memMaskGran = Some(9)
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
@@ -15,14 +15,15 @@ trait HasSimpleWidthTestGenerator extends HasSimpleTestGenerator {
|
||||
|
||||
// Generate mem_0_<i> lines for number of width instances.
|
||||
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}
|
||||
"""
|
||||
}).reduceLeft(_ + _)
|
||||
)
|
||||
|
||||
// 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.
|
||||
val myMemWidth = if (i == widthInstances - 1) lastWidthBits else usableLibWidth
|
||||
// Base bit of this submemory.
|
||||
@@ -39,7 +40,8 @@ trait HasSimpleWidthTestGenerator extends HasSimpleTestGenerator {
|
||||
s"bits(outer_mask, ${outerMaskBit}, ${outerMaskBit})"
|
||||
} else """UInt<1>("h1")"""
|
||||
val chipEnable = s"""UInt<1>("h1")"""
|
||||
val writeEnableExpr = if (libMaskGran.isEmpty) s"and(${memPortPrefix}_write_en, ${chipEnable})" else s"${memPortPrefix}_write_en"
|
||||
val writeEnableExpr =
|
||||
if (libMaskGran.isEmpty) s"and(${memPortPrefix}_write_en, ${chipEnable})" else s"${memPortPrefix}_write_en"
|
||||
|
||||
s"""
|
||||
mem_0_${i}.${libPortPrefix}_clk <= ${memPortPrefix}_clk
|
||||
@@ -49,22 +51,21 @@ s"""
|
||||
${maskStatement}
|
||||
mem_0_${i}.${libPortPrefix}_write_en <= and(and(${writeEnableExpr}, ${writeEnableBit}), UInt<1>("h1"))
|
||||
"""
|
||||
}).reduceLeft(_ + _)
|
||||
}).reduceLeft(_ + _))
|
||||
|
||||
// Generate final output that concats together the sub-memories.
|
||||
// e.g. cat(outer_dout_0_2, cat(outer_dout_0_1, outer_dout_0_0))
|
||||
output append {
|
||||
val doutStatements = ((widthInstances - 1 to 0 by -1) map (i => s"${memPortPrefix}_dout_0_${i}"))
|
||||
output.append {
|
||||
val doutStatements = ((widthInstances - 1 to 0 by -1).map(i => s"${memPortPrefix}_dout_0_${i}"))
|
||||
val catStmt = doutStatements.init.foldRight(doutStatements.last)((l: String, r: String) => s"cat($l, $r)")
|
||||
s"""
|
||||
node ${memPortPrefix}_dout_0 = ${catStmt}
|
||||
"""
|
||||
}
|
||||
|
||||
output append
|
||||
s"""
|
||||
output.append(s"""
|
||||
${memPortPrefix}_dout <= mux(UInt<1>("h1"), ${memPortPrefix}_dout_0, UInt<${memWidth}>("h0"))
|
||||
"""
|
||||
""")
|
||||
output.toString
|
||||
}
|
||||
}
|
||||
@@ -268,7 +269,10 @@ class SplitWidth1024x16_mem11_rw extends MacroCompilerSpec with HasSRAMGenerator
|
||||
|
||||
// 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 memWidth = 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)
|
||||
}
|
||||
|
||||
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 memWidth = 16
|
||||
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)
|
||||
}
|
||||
|
||||
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 memWidth = 16
|
||||
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)
|
||||
}
|
||||
|
||||
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 memWidth = 128
|
||||
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)
|
||||
}
|
||||
|
||||
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 memWidth = 16
|
||||
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)
|
||||
}
|
||||
|
||||
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 memWidth = 16
|
||||
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)
|
||||
}
|
||||
|
||||
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 memWidth = 16
|
||||
override lazy val libWidth = 8
|
||||
@@ -360,7 +382,10 @@ class SplitWidth1024x16_libGran_1_rw extends MacroCompilerSpec with HasSRAMGener
|
||||
|
||||
// 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 memWidth = 16
|
||||
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
|
||||
|
||||
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 memWidth = 16
|
||||
override lazy val libWidth = 8
|
||||
override lazy val memMaskGran = Some(9)
|
||||
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)
|
||||
//~ execute(mem, lib, false, output)
|
||||
}
|
||||
|
||||
// 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._
|
||||
|
||||
override lazy val depth = BigInt(1024)
|
||||
@@ -399,11 +430,18 @@ class SplitWidth1024x32_readEnable_Lib extends MacroCompilerSpec with HasSRAMGen
|
||||
width = libWidth,
|
||||
depth = libDepth,
|
||||
family = "1rw",
|
||||
ports=Seq(generateTestPort(
|
||||
"lib", Some(libWidth), Some(libDepth), maskGran=libMaskGran,
|
||||
write=true, writeEnable=true,
|
||||
read=true, readEnable=true
|
||||
))
|
||||
ports = Seq(
|
||||
generateTestPort(
|
||||
"lib",
|
||||
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)
|
||||
}
|
||||
|
||||
class SplitWidth1024x32_readEnable_Mem extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
|
||||
class SplitWidth1024x32_readEnable_Mem
|
||||
extends MacroCompilerSpec
|
||||
with HasSRAMGenerator
|
||||
with HasSimpleWidthTestGenerator {
|
||||
import mdf.macrolib._
|
||||
|
||||
override lazy val depth = BigInt(1024)
|
||||
@@ -457,11 +498,18 @@ class SplitWidth1024x32_readEnable_Mem extends MacroCompilerSpec with HasSRAMGen
|
||||
width = memWidth,
|
||||
depth = memDepth,
|
||||
family = "1rw",
|
||||
ports=Seq(generateTestPort(
|
||||
"outer", Some(memWidth), Some(memDepth), maskGran=memMaskGran,
|
||||
write=true, writeEnable=true,
|
||||
read=true, readEnable=true
|
||||
))
|
||||
ports = Seq(
|
||||
generateTestPort(
|
||||
"outer",
|
||||
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)
|
||||
}
|
||||
|
||||
class SplitWidth1024x32_readEnable_LibMem extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
|
||||
class SplitWidth1024x32_readEnable_LibMem
|
||||
extends MacroCompilerSpec
|
||||
with HasSRAMGenerator
|
||||
with HasSimpleWidthTestGenerator {
|
||||
import mdf.macrolib._
|
||||
|
||||
override lazy val depth = BigInt(1024)
|
||||
@@ -483,11 +534,18 @@ class SplitWidth1024x32_readEnable_LibMem extends MacroCompilerSpec with HasSRAM
|
||||
width = libWidth,
|
||||
depth = libDepth,
|
||||
family = "1rw",
|
||||
ports=Seq(generateTestPort(
|
||||
"lib", Some(libWidth), Some(libDepth), maskGran=libMaskGran,
|
||||
write=true, writeEnable=true,
|
||||
read=true, readEnable=true
|
||||
))
|
||||
ports = Seq(
|
||||
generateTestPort(
|
||||
"lib",
|
||||
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,
|
||||
depth = memDepth,
|
||||
family = "1rw",
|
||||
ports=Seq(generateTestPort(
|
||||
"outer", Some(memWidth), Some(memDepth), maskGran=memMaskGran,
|
||||
write=true, writeEnable=true,
|
||||
read=true, readEnable=true
|
||||
))
|
||||
ports = Seq(
|
||||
generateTestPort(
|
||||
"outer",
|
||||
Some(memWidth),
|
||||
Some(memDepth),
|
||||
maskGran = memMaskGran,
|
||||
write = true,
|
||||
writeEnable = true,
|
||||
read = true,
|
||||
readEnable = true
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -29,8 +29,8 @@ class WriteEnableTest extends MacroCompilerSpec with HasSRAMGenerator {
|
||||
|
||||
override val libPrefix = "macros/src/test/resources"
|
||||
|
||||
val memSRAMs = mdf.macrolib.Utils.readMDFFromString(
|
||||
"""
|
||||
val memSRAMs = mdf.macrolib.Utils
|
||||
.readMDFFromString("""
|
||||
[ {
|
||||
"type" : "sram",
|
||||
"name" : "cc_banks_0_ext",
|
||||
@@ -99,8 +99,8 @@ class MaskPortTest extends MacroCompilerSpec with HasSRAMGenerator {
|
||||
|
||||
override val libPrefix = "macros/src/test/resources"
|
||||
|
||||
val memSRAMs = mdf.macrolib.Utils.readMDFFromString(
|
||||
"""
|
||||
val memSRAMs = mdf.macrolib.Utils
|
||||
.readMDFFromString("""
|
||||
[ {
|
||||
"type" : "sram",
|
||||
"name" : "cc_dir_ext",
|
||||
@@ -183,8 +183,8 @@ class BOOMTest extends MacroCompilerSpec with HasSRAMGenerator {
|
||||
|
||||
override val libPrefix = "macros/src/test/resources"
|
||||
|
||||
val memSRAMs = mdf.macrolib.Utils.readMDFFromString(
|
||||
"""
|
||||
val memSRAMs = mdf.macrolib.Utils
|
||||
.readMDFFromString("""
|
||||
[ {
|
||||
"type" : "sram",
|
||||
"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",
|
||||
|
||||
@@ -47,7 +47,8 @@ s"""
|
||||
// If there is no lib, don't generate a footer, since the flops definition
|
||||
// will be in the body.
|
||||
override def generateFooter = {
|
||||
if (this.isInstanceOf[HasNoLibTestGenerator]) "" else
|
||||
if (this.isInstanceOf[HasNoLibTestGenerator]) ""
|
||||
else
|
||||
s"""
|
||||
module ${lib_name} :
|
||||
${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 memWidth = 8
|
||||
|
||||
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 memWidth = 16
|
||||
|
||||
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 memWidth = 16
|
||||
|
||||
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 libDepth = BigInt(1024)
|
||||
override lazy val width = 16
|
||||
@@ -87,7 +104,11 @@ class Synflops2048x16_depth_Lib extends MacroCompilerSpec with HasSRAMGenerator
|
||||
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 libWidth = 8
|
||||
override lazy val depth = BigInt(1024)
|
||||
@@ -95,7 +116,11 @@ class Synflops2048x64_width_Lib extends MacroCompilerSpec with HasSRAMGenerator
|
||||
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._
|
||||
|
||||
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._
|
||||
|
||||
override lazy val memDepth = BigInt(2048)
|
||||
|
||||
Reference in New Issue
Block a user