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