summaryrefslogtreecommitdiff
path: root/src/main/scala/chisel3/util/experimental
diff options
context:
space:
mode:
authorJack Koenig2022-01-10 10:39:52 -0800
committerJack Koenig2022-01-10 15:53:55 -0800
commit3131c0daad41dea78bede4517669e376c41a325a (patch)
tree55baed78a6a01f80ff3952a08233ca553a19964f /src/main/scala/chisel3/util/experimental
parentdd36f97a82746cec0b25b94651581fe799e24579 (diff)
Apply scalafmt
Command: sbt scalafmtAll
Diffstat (limited to 'src/main/scala/chisel3/util/experimental')
-rw-r--r--src/main/scala/chisel3/util/experimental/BoringUtils.scala59
-rw-r--r--src/main/scala/chisel3/util/experimental/ForceNames.scala62
-rw-r--r--src/main/scala/chisel3/util/experimental/Inline.scala32
-rw-r--r--src/main/scala/chisel3/util/experimental/LoadMemoryTransform.scala95
-rw-r--r--src/main/scala/chisel3/util/experimental/decode/EspressoMinimizer.scala19
-rw-r--r--src/main/scala/chisel3/util/experimental/decode/Minimizer.scala3
-rw-r--r--src/main/scala/chisel3/util/experimental/decode/QMCMinimizer.scala78
-rw-r--r--src/main/scala/chisel3/util/experimental/decode/TruthTable.scala66
-rw-r--r--src/main/scala/chisel3/util/experimental/decode/decoder.scala15
-rw-r--r--src/main/scala/chisel3/util/experimental/getAnnotations.scala1
-rw-r--r--src/main/scala/chisel3/util/experimental/group.scala17
11 files changed, 255 insertions, 192 deletions
diff --git a/src/main/scala/chisel3/util/experimental/BoringUtils.scala b/src/main/scala/chisel3/util/experimental/BoringUtils.scala
index f2a3e757..254f83a4 100644
--- a/src/main/scala/chisel3/util/experimental/BoringUtils.scala
+++ b/src/main/scala/chisel3/util/experimental/BoringUtils.scala
@@ -3,11 +3,11 @@
package chisel3.util.experimental
import chisel3._
-import chisel3.experimental.{ChiselAnnotation, RunFirrtlTransform, annotate}
+import chisel3.experimental.{annotate, ChiselAnnotation, RunFirrtlTransform}
import chisel3.internal.{InstanceId, NamedComponent, Namespace}
import firrtl.transforms.{DontTouchAnnotation, NoDedupAnnotation}
-import firrtl.passes.wiring.{WiringTransform, SourceAnnotation, SinkAnnotation}
-import firrtl.annotations.{ModuleName, ComponentName}
+import firrtl.passes.wiring.{SinkAnnotation, SourceAnnotation, WiringTransform}
+import firrtl.annotations.{ComponentName, ModuleName}
import scala.concurrent.SyncVar
@@ -122,20 +122,25 @@ object BoringUtils {
* @note if a uniqueName is not specified, the returned name may differ from the user-provided name
*/
def addSource(
- component: NamedComponent,
- name: String,
+ component: NamedComponent,
+ name: String,
disableDedup: Boolean = false,
- uniqueName: Boolean = false): String = {
+ uniqueName: Boolean = false
+ ): String = {
- val id = if (uniqueName) { newName(name) } else { name }
+ val id = if (uniqueName) { newName(name) }
+ else { name }
val maybeDedup =
if (disableDedup) { Seq(new ChiselAnnotation { def toFirrtl = NoDedupAnnotation(component.toNamed.module) }) }
- else { Seq[ChiselAnnotation]() }
+ else { Seq[ChiselAnnotation]() }
val annotations =
- Seq(new ChiselAnnotation with RunFirrtlTransform {
- def toFirrtl = SourceAnnotation(component.toNamed, id)
- def transformClass = classOf[WiringTransform] },
- new ChiselAnnotation { def toFirrtl = DontTouchAnnotation(component.toNamed) } ) ++ maybeDedup
+ Seq(
+ new ChiselAnnotation with RunFirrtlTransform {
+ def toFirrtl = SourceAnnotation(component.toNamed, id)
+ def transformClass = classOf[WiringTransform]
+ },
+ new ChiselAnnotation { def toFirrtl = DontTouchAnnotation(component.toNamed) }
+ ) ++ maybeDedup
annotations.foreach(annotate(_))
id
@@ -150,25 +155,28 @@ object BoringUtils {
* @throws BoringUtilsException if name is expected to exist and it doesn't
*/
def addSink(
- component: InstanceId,
- name: String,
+ component: InstanceId,
+ name: String,
disableDedup: Boolean = false,
- forceExists: Boolean = false): Unit = {
+ forceExists: Boolean = false
+ ): Unit = {
if (forceExists && !checkName(name)) {
- throw new BoringUtilsException(s"Sink ID '$name' not found in BoringUtils ID namespace") }
+ throw new BoringUtilsException(s"Sink ID '$name' not found in BoringUtils ID namespace")
+ }
def moduleName = component.toNamed match {
- case c: ModuleName => c
+ case c: ModuleName => c
case c: ComponentName => c.module
case _ => throw new ChiselException("Can only add a Module or Component sink", null)
}
val maybeDedup =
if (disableDedup) { Seq(new ChiselAnnotation { def toFirrtl = NoDedupAnnotation(moduleName) }) }
- else { Seq[ChiselAnnotation]() }
+ else { Seq[ChiselAnnotation]() }
val annotations =
Seq(new ChiselAnnotation with RunFirrtlTransform {
- def toFirrtl = SinkAnnotation(component.toNamed, name)
- def transformClass = classOf[WiringTransform] }) ++ maybeDedup
+ def toFirrtl = SinkAnnotation(component.toNamed, name)
+ def transformClass = classOf[WiringTransform]
+ }) ++ maybeDedup
annotations.foreach(annotate(_))
}
@@ -181,11 +189,12 @@ object BoringUtils {
* component
*/
def bore(source: Data, sinks: Seq[Data]): String = {
- val boringName = try {
- source.instanceName
- } catch {
- case _: Exception => "bore"
- }
+ val boringName =
+ try {
+ source.instanceName
+ } catch {
+ case _: Exception => "bore"
+ }
val genName = addSource(source, boringName, true, true)
sinks.foreach(addSink(_, genName, true, true))
genName
diff --git a/src/main/scala/chisel3/util/experimental/ForceNames.scala b/src/main/scala/chisel3/util/experimental/ForceNames.scala
index bac69ed4..53ee2bd2 100644
--- a/src/main/scala/chisel3/util/experimental/ForceNames.scala
+++ b/src/main/scala/chisel3/util/experimental/ForceNames.scala
@@ -2,7 +2,7 @@
package chisel3.util.experimental
-import chisel3.experimental.{ChiselAnnotation, RunFirrtlTransform, annotate}
+import chisel3.experimental.{annotate, ChiselAnnotation, RunFirrtlTransform}
import firrtl.Mappers._
import firrtl._
import firrtl.annotations._
@@ -49,7 +49,7 @@ object forceName {
* @param instance Instance to name
*/
def apply(instance: chisel3.experimental.BaseModule, name: String): Unit = {
- annotate(new ChiselAnnotation with RunFirrtlTransform {
+ annotate(new ChiselAnnotation with RunFirrtlTransform {
def toFirrtl = {
val t = instance.toAbsoluteTarget
ForceNameAnnotation(t, name)
@@ -64,7 +64,7 @@ object forceName {
* @param instance Signal to name
*/
def apply(instance: chisel3.experimental.BaseModule): Unit = {
- annotate(new ChiselAnnotation with RunFirrtlTransform {
+ annotate(new ChiselAnnotation with RunFirrtlTransform {
def toFirrtl = {
val t = instance.toAbsoluteTarget
ForceNameAnnotation(t, instance.instanceName)
@@ -80,8 +80,7 @@ object forceName {
* @param target signal/instance to force the name
* @param name name to force it to be
*/
-case class ForceNameAnnotation(target: IsMember, name: String)
- extends SingleTargetAnnotation[IsMember] {
+case class ForceNameAnnotation(target: IsMember, name: String) extends SingleTargetAnnotation[IsMember] {
def duplicate(n: IsMember): ForceNameAnnotation = this.copy(target = n, name)
// Errors if renaming to multiple targets
@@ -105,6 +104,7 @@ case class ForceNameAnnotation(target: IsMember, name: String)
* Could (should?) be moved to FIRRTL.
*/
private object ForceNamesTransform {
+
/** Returns the [[IsModule]] which is referred to, or if a [[ReferenceTarget]], the enclosing [[IsModule]]
*
* @param a signal/instance/module
@@ -123,10 +123,12 @@ private object ForceNamesTransform {
*/
def allInstancePaths(graph: InstanceKeyGraph): IsModule => List[List[(Instance, OfModule)]] = {
val lookup: String => List[List[(Instance, OfModule)]] =
- str => graph.findInstancesInHierarchy(str)
- .view
- .map(_.map(_.toTokens).toList)
- .toList
+ str =>
+ graph
+ .findInstancesInHierarchy(str)
+ .view
+ .map(_.map(_.toTokens).toList)
+ .toList
allInstancePaths(lookup) _
}
@@ -136,8 +138,10 @@ private object ForceNamesTransform {
* @param target target to get all instance paths to
* @return
*/
- def allInstancePaths(lookup: String => List[List[(Instance, OfModule)]])
- (target: IsModule): List[List[(Instance, OfModule)]] = {
+ def allInstancePaths(
+ lookup: String => List[List[(Instance, OfModule)]]
+ )(target: IsModule
+ ): List[List[(Instance, OfModule)]] = {
target match {
case ModuleTarget(circuit, module) =>
if (circuit == module) List(List((Instance(module), OfModule(module))))
@@ -149,16 +153,13 @@ private object ForceNamesTransform {
}
}
-
/** Builds the map of module name to map of old signal/instance name to new signal/instance name
*
* @param state CircuitState to operate on
* @param igraph built instance key graph from state's circuit
* @return
*/
- def buildForceNameMap(state: CircuitState,
- igraph: => InstanceKeyGraph
- ): Option[Map[String, Map[String, String]]] = {
+ def buildForceNameMap(state: CircuitState, igraph: => InstanceKeyGraph): Option[Map[String, Map[String, String]]] = {
val forceNames = state.annotations.collect { case f: ForceNameAnnotation => f }
val badNames = mutable.HashSet[ForceNameAnnotation]()
val allNameMaps = forceNames.groupBy { case f => referringIsModule(f.target) }.mapValues { value =>
@@ -207,9 +208,9 @@ private object ForceNamesTransform {
* - Use to avoid prefixing behavior on specific instances whose enclosing modules are inlined
*/
class ForceNamesTransform extends Transform with DependencyAPIMigration {
- override def optionalPrerequisites: Seq[TransformDependency] = Seq(Dependency[InlineInstances])
+ override def optionalPrerequisites: Seq[TransformDependency] = Seq(Dependency[InlineInstances])
override def optionalPrerequisiteOf: Seq[TransformDependency] = Forms.LowEmitters
- override def prerequisites: Seq[TransformDependency] = Seq(Dependency(LowerTypes))
+ override def prerequisites: Seq[TransformDependency] = Seq(Dependency(LowerTypes))
override def invalidates(a: Transform): Boolean = firrtl.passes.InferTypes == a
import ForceNamesTransform._
@@ -226,22 +227,23 @@ class ForceNamesTransform extends Transform with DependencyAPIMigration {
*/
private def forceNamesInModule(
modToNames: Map[String, Map[String, String]],
- renameMap: RenameMap,
- ct: CircuitTarget,
- igraph: InstanceKeyGraph
- )(mod: DefModule): DefModule = {
+ renameMap: RenameMap,
+ ct: CircuitTarget,
+ igraph: InstanceKeyGraph
+ )(mod: DefModule
+ ): DefModule = {
val mt = ct.module(mod.name)
val instToOfModule = mutable.HashMap[String, String]()
val names = modToNames.getOrElse(mod.name, Map.empty[String, String])
// Need to find WRef referring to mems for prefixing
def onExpr(expr: Expression): Expression = expr match {
- case ref @ Reference(n, _,_,_) if names.contains(n) =>
+ case ref @ Reference(n, _, _, _) if names.contains(n) =>
ref.copy(name = names(n))
- case sub @ SubField(WRef(i, _, _, _), p,_,_) if instToOfModule.contains(i) =>
+ case sub @ SubField(WRef(i, _, _, _), p, _, _) if instToOfModule.contains(i) =>
val newsub = modToNames.get(instToOfModule(i)) match {
case Some(map) if map.contains(p) => sub.copy(name = map(p))
- case _ => sub
+ case _ => sub
}
newsub.map(onExpr)
case other => other.map(onExpr)
@@ -269,17 +271,19 @@ class ForceNamesTransform extends Transform with DependencyAPIMigration {
} else port
}
- val childInstanceHasRename = igraph.getChildInstanceMap(OfModule(mod.name)).exists {
- o => modToNames.contains(o._2.value)
+ val childInstanceHasRename = igraph.getChildInstanceMap(OfModule(mod.name)).exists { o =>
+ modToNames.contains(o._2.value)
}
- if(childInstanceHasRename || modToNames.contains(mod.name)) {
+ if (childInstanceHasRename || modToNames.contains(mod.name)) {
val ns = Namespace(mod)
val conflicts = names.values.collect { case k if ns.contains(k) => k }
- if(conflicts.isEmpty) {
+ if (conflicts.isEmpty) {
mod.map(onPort).map(onStmt)
} else {
- throw new FirrtlUserException(s"Cannot force the following names in module ${mod.name} because they conflict: ${conflicts.mkString(",")}")
+ throw new FirrtlUserException(
+ s"Cannot force the following names in module ${mod.name} because they conflict: ${conflicts.mkString(",")}"
+ )
}
} else mod
}
diff --git a/src/main/scala/chisel3/util/experimental/Inline.scala b/src/main/scala/chisel3/util/experimental/Inline.scala
index 1d5fcb89..fd5c6aa5 100644
--- a/src/main/scala/chisel3/util/experimental/Inline.scala
+++ b/src/main/scala/chisel3/util/experimental/Inline.scala
@@ -6,7 +6,7 @@ import chisel3._
import chisel3.experimental.{BaseModule, ChiselAnnotation, RunFirrtlTransform}
import firrtl.Transform
import firrtl.passes.{InlineAnnotation, InlineInstances}
-import firrtl.transforms.{NoDedupAnnotation, FlattenAnnotation, Flatten}
+import firrtl.transforms.{Flatten, FlattenAnnotation, NoDedupAnnotation}
import firrtl.annotations.Annotation
/** Inlines an instance of a module
@@ -40,11 +40,15 @@ import firrtl.annotations.Annotation
* }}}
*/
trait InlineInstance { self: BaseModule =>
- Seq(new ChiselAnnotation with RunFirrtlTransform {
- def toFirrtl: Annotation = InlineAnnotation(self.toNamed)
- def transformClass: Class[_ <: Transform] = classOf[InlineInstances] },
- new ChiselAnnotation {
- def toFirrtl: Annotation = NoDedupAnnotation(self.toNamed) })
+ Seq(
+ new ChiselAnnotation with RunFirrtlTransform {
+ def toFirrtl: Annotation = InlineAnnotation(self.toNamed)
+ def transformClass: Class[_ <: Transform] = classOf[InlineInstances]
+ },
+ new ChiselAnnotation {
+ def toFirrtl: Annotation = NoDedupAnnotation(self.toNamed)
+ }
+ )
.map(chisel3.experimental.annotate(_))
}
@@ -75,10 +79,14 @@ trait InlineInstance { self: BaseModule =>
* }}}
*/
trait FlattenInstance { self: BaseModule =>
- Seq(new ChiselAnnotation with RunFirrtlTransform {
- def toFirrtl: Annotation = FlattenAnnotation(self.toNamed)
- def transformClass: Class[_ <: Transform] = classOf[Flatten] },
- new ChiselAnnotation {
- def toFirrtl: Annotation = NoDedupAnnotation(self.toNamed) })
- .map(chisel3.experimental.annotate(_))
+ Seq(
+ new ChiselAnnotation with RunFirrtlTransform {
+ def toFirrtl: Annotation = FlattenAnnotation(self.toNamed)
+ def transformClass: Class[_ <: Transform] = classOf[Flatten]
+ },
+ new ChiselAnnotation {
+ def toFirrtl: Annotation = NoDedupAnnotation(self.toNamed)
+ }
+ )
+ .map(chisel3.experimental.annotate(_))
}
diff --git a/src/main/scala/chisel3/util/experimental/LoadMemoryTransform.scala b/src/main/scala/chisel3/util/experimental/LoadMemoryTransform.scala
index 93981485..bd46abe9 100644
--- a/src/main/scala/chisel3/util/experimental/LoadMemoryTransform.scala
+++ b/src/main/scala/chisel3/util/experimental/LoadMemoryTransform.scala
@@ -3,7 +3,7 @@
package chisel3.util.experimental
import chisel3._
-import chisel3.experimental.{RunFirrtlTransform, annotate, ChiselAnnotation}
+import chisel3.experimental.{annotate, ChiselAnnotation, RunFirrtlTransform}
import firrtl.annotations._
import firrtl.ir.{Module => _, _}
import firrtl.transforms.BlackBoxInlineAnno
@@ -21,11 +21,11 @@ import scala.collection.mutable
case class ChiselLoadMemoryAnnotation[T <: Data](
target: MemBase[T],
fileName: String,
- hexOrBinary: MemoryLoadFileType.FileType = MemoryLoadFileType.Hex
-)
- extends ChiselAnnotation with RunFirrtlTransform {
+ hexOrBinary: MemoryLoadFileType.FileType = MemoryLoadFileType.Hex)
+ extends ChiselAnnotation
+ with RunFirrtlTransform {
- if(fileName.isEmpty) {
+ if (fileName.isEmpty) {
throw new Exception(
s"""LoadMemory from file annotations file empty file name"""
)
@@ -39,7 +39,6 @@ case class ChiselLoadMemoryAnnotation[T <: Data](
}
}
-
/** [[loadMemoryFromFile]] is an annotation generator that helps with loading a memory from a text file as a bind module. This relies on
* Verilator and Verilog's `\$readmemh` or `\$readmemb`. The [[https://github.com/freechipsproject/treadle Treadle
* backend]] can also recognize this annotation and load memory at run-time.
@@ -101,22 +100,20 @@ case class ChiselLoadMemoryAnnotation[T <: Data](
*/
object loadMemoryFromFile {
-
/** Annotate a memory such that it can be initialized using a file
* @param memory the memory
* @param filename the file used for initialization
* @param hexOrBinary whether the file uses a hex or binary number representation
*/
def apply[T <: Data](
- memory: MemBase[T],
- fileName: String,
+ memory: MemBase[T],
+ fileName: String,
hexOrBinary: MemoryLoadFileType.FileType = MemoryLoadFileType.Hex
): Unit = {
annotate(ChiselLoadMemoryAnnotation(memory, fileName, hexOrBinary))
}
}
-
/** [[loadMemoryFromFileInline]] is an annotation generator that helps with loading a memory from a text file inlined in
* the Verilog module. This relies on Verilator and Verilog's `\$readmemh` or `\$readmemb`.
* The [[https://github.com/freechipsproject/treadle Treadlebackend]] can also recognize this annotation and load memory at run-time.
@@ -179,15 +176,14 @@ object loadMemoryFromFile {
*/
object loadMemoryFromFileInline {
-
/** Annotate a memory such that it can be initialized inline using a file
* @param memory the memory
* @param fileName the file used for initialization
* @param hexOrBinary whether the file uses a hex or binary number representation
*/
def apply[T <: Data](
- memory: MemBase[T],
- fileName: String,
+ memory: MemBase[T],
+ fileName: String,
hexOrBinary: MemoryLoadFileType.FileType = MemoryLoadFileType.Hex
): Unit = {
annotate(new ChiselAnnotation {
@@ -204,14 +200,14 @@ object loadMemoryFromFileInline {
* not need this transform to do that.
*/
class LoadMemoryTransform extends Transform {
- def inputForm: CircuitForm = LowForm
+ def inputForm: CircuitForm = LowForm
def outputForm: CircuitForm = LowForm
private var memoryCounter: Int = -1
private val bindModules: mutable.ArrayBuffer[BlackBoxInlineAnno] = new mutable.ArrayBuffer()
- private val verilogEmitter: VerilogEmitter = new VerilogEmitter
+ private val verilogEmitter: VerilogEmitter = new VerilogEmitter
/** run the pass
* @param circuit the circuit
@@ -219,19 +215,19 @@ class LoadMemoryTransform extends Transform {
* @return
*/
def run(circuit: Circuit, annotations: AnnotationSeq): Circuit = {
- val groups = annotations
- .collect{ case m: LoadMemoryAnnotation => m }
+ val groups = annotations.collect { case m: LoadMemoryAnnotation => m }
.groupBy(_.target.serialize)
- val memoryAnnotations = groups.map { case (key, annos) =>
+ val memoryAnnotations = groups.map {
+ case (key, annos) =>
if (annos.size > 1) {
throw new Exception(
s"Multiple (${annos.size} found for memory $key one LoadMemoryAnnotation is allowed per memory"
)
}
key -> annos.head
- }
+ }
- val modulesByName = circuit.modules.collect { case module: firrtl.ir.Module => module.name -> module }.toMap
+ val modulesByName = circuit.modules.collect { case module: firrtl.ir.Module => module.name -> module }.toMap
/* Walk the module and for memories that are annotated with [[LoadMemoryAnnotation]]s generate the bindable modules for
* Verilog emission.
@@ -251,32 +247,34 @@ class LoadMemoryTransform extends Transform {
val writer = new java.io.StringWriter
val readmem = hexOrBinary match {
case MemoryLoadFileType.Binary => "$readmemb"
- case MemoryLoadFileType.Hex => "$readmemh"
+ case MemoryLoadFileType.Hex => "$readmemh"
}
modulesByName.get(moduleName.name).foreach { module =>
- val renderer = verilogEmitter.getRenderer(module, modulesByName)(writer)
- val loadFileName = lma.getFileName
-
- memoryCounter += 1
- val bindsToName = s"BindsTo_${memoryCounter}_${moduleName.name}"
- renderer.emitVerilogBind(bindsToName,
- s"""
- |initial begin
- | $readmem("$loadFileName", ${myModule.name}.$componentName);
- |end
- """.stripMargin)
- val inLineText = writer.toString + "\n" +
- s"""bind ${myModule.name} $bindsToName ${bindsToName}_Inst(.*);"""
-
- val blackBoxInline = BlackBoxInlineAnno(
- moduleName,
- moduleName.serialize + "." + componentName + ".v",
- inLineText
- )
-
- bindModules += blackBoxInline
- }
+ val renderer = verilogEmitter.getRenderer(module, modulesByName)(writer)
+ val loadFileName = lma.getFileName
+
+ memoryCounter += 1
+ val bindsToName = s"BindsTo_${memoryCounter}_${moduleName.name}"
+ renderer.emitVerilogBind(
+ bindsToName,
+ s"""
+ |initial begin
+ | $readmem("$loadFileName", ${myModule.name}.$componentName);
+ |end
+ """.stripMargin
+ )
+ val inLineText = writer.toString + "\n" +
+ s"""bind ${myModule.name} $bindsToName ${bindsToName}_Inst(.*);"""
+
+ val blackBoxInline = BlackBoxInlineAnno(
+ moduleName,
+ moduleName.serialize + "." + componentName + ".v",
+ inLineText
+ )
+
+ bindModules += blackBoxInline
+ }
case _ =>
}
@@ -284,8 +282,8 @@ class LoadMemoryTransform extends Transform {
def processStatements(statement: Statement): Statement = {
statement match {
- case m: DefMemory => processMemory(m.name)
- case s => s map processStatements
+ case m: DefMemory => processMemory(m.name)
+ case s => s.map(processStatements)
}
statement
}
@@ -299,7 +297,7 @@ class LoadMemoryTransform extends Transform {
myModule
}
- circuit map processModule
+ circuit.map(processModule)
}
def execute(state: CircuitState): CircuitState = {
@@ -309,11 +307,10 @@ class LoadMemoryTransform extends Transform {
case _ =>
false
}
- if(isVerilog) {
+ if (isVerilog) {
run(state.circuit, state.annotations)
state.copy(annotations = state.annotations ++ bindModules)
- }
- else {
+ } else {
state
}
}
diff --git a/src/main/scala/chisel3/util/experimental/decode/EspressoMinimizer.scala b/src/main/scala/chisel3/util/experimental/decode/EspressoMinimizer.scala
index 4dcea99e..de2f207b 100644
--- a/src/main/scala/chisel3/util/experimental/decode/EspressoMinimizer.scala
+++ b/src/main/scala/chisel3/util/experimental/decode/EspressoMinimizer.scala
@@ -19,7 +19,7 @@ case object EspressoNotFoundException extends Exception
*/
object EspressoMinimizer extends Minimizer with LazyLogging {
def minimize(table: TruthTable): TruthTable =
- TruthTable.merge(TruthTable.split(table).map{case (table, indexes) => (espresso(table), indexes)})
+ TruthTable.merge(TruthTable.split(table).map { case (table, indexes) => (espresso(table), indexes) })
private def espresso(table: TruthTable): TruthTable = {
def writeTable(table: TruthTable): String = {
@@ -34,10 +34,9 @@ object EspressoMinimizer extends Minimizer with LazyLogging {
}
val tableType: String = defaultType match {
case '?' => "fr"
- case _ => "fd"
+ case _ => "fd"
}
- val rawTable = table
- .toString
+ val rawTable = table.toString
.split("\n")
.filter(_.contains("->"))
.mkString("\n")
@@ -69,11 +68,13 @@ object EspressoMinimizer extends Minimizer with LazyLogging {
logger.trace(s"""espresso input table:
|$input
|""".stripMargin)
- val output = try {
- os.proc("espresso").call(stdin = input).out.chunks.mkString
- } catch {
- case e: java.io.IOException if e.getMessage.contains("error=2, No such file or directory") => throw EspressoNotFoundException
- }
+ val output =
+ try {
+ os.proc("espresso").call(stdin = input).out.chunks.mkString
+ } catch {
+ case e: java.io.IOException if e.getMessage.contains("error=2, No such file or directory") =>
+ throw EspressoNotFoundException
+ }
logger.trace(s"""espresso output table:
|$output
|""".stripMargin)
diff --git a/src/main/scala/chisel3/util/experimental/decode/Minimizer.scala b/src/main/scala/chisel3/util/experimental/decode/Minimizer.scala
index 86847710..c4065ac9 100644
--- a/src/main/scala/chisel3/util/experimental/decode/Minimizer.scala
+++ b/src/main/scala/chisel3/util/experimental/decode/Minimizer.scala
@@ -3,6 +3,7 @@
package chisel3.util.experimental.decode
abstract class Minimizer {
+
/** Minimize a multi-input multi-output logic function given by the truth table `table`, with function output values
* on unspecified inputs treated as `default`, and return a minimized PLA-like representation of the function.
*
@@ -26,4 +27,4 @@ abstract class Minimizer {
* }}}
*/
def minimize(table: TruthTable): TruthTable
-} \ No newline at end of file
+}
diff --git a/src/main/scala/chisel3/util/experimental/decode/QMCMinimizer.scala b/src/main/scala/chisel3/util/experimental/decode/QMCMinimizer.scala
index 59120221..a3481869 100644
--- a/src/main/scala/chisel3/util/experimental/decode/QMCMinimizer.scala
+++ b/src/main/scala/chisel3/util/experimental/decode/QMCMinimizer.scala
@@ -125,12 +125,15 @@ object QMCMinimizer extends Minimizer {
* b: nonessential prime implicants
* c: implicants that are not cover by any of the essential prime implicants
*/
- private def getEssentialPrimeImplicants(primes: Seq[Implicant], minterms: Seq[Implicant]): (Seq[Implicant], Seq[Implicant], Seq[Implicant]) = {
+ private def getEssentialPrimeImplicants(
+ primes: Seq[Implicant],
+ minterms: Seq[Implicant]
+ ): (Seq[Implicant], Seq[Implicant], Seq[Implicant]) = {
// primeCovers(i): implicants that `prime(i)` covers
val primeCovers = primes.map(p => minterms.filter(p.covers))
// eliminate prime implicants that can be covered by other prime implicants
- for (((icover, pi), i) <- (primeCovers zip primes).zipWithIndex) {
- for (((jcover, pj), _) <- (primeCovers zip primes).zipWithIndex.drop(i + 1)) {
+ for (((icover, pi), i) <- (primeCovers.zip(primes)).zipWithIndex) {
+ for (((jcover, pj), _) <- (primeCovers.zip(primes)).zipWithIndex.drop(i + 1)) {
// we prefer prime implicants with wider implicants coverage
if (icover.size > jcover.size && jcover.forall(pi.covers)) {
// calculate essential prime implicants with `pj` eliminated from prime implicants table
@@ -165,6 +168,7 @@ object QMCMinimizer extends Minimizer {
* @return Selected nonessential prime implicants
*/
private def getCover(implicants: Seq[Implicant], minterms: Seq[Implicant]): Seq[Implicant] = {
+
/** Calculate the implementation cost (using comparators) of a list of implicants, more don't cares is cheaper
*
* @param cover Implicant list
@@ -193,7 +197,8 @@ object QMCMinimizer extends Minimizer {
* @return `a` < `b`
*/
@tailrec
- def listLess(a: Seq[Implicant], b: Seq[Implicant]): Boolean = b.nonEmpty && (a.isEmpty || a.head < b.head || a.head == b.head && listLess(a.tail, b.tail))
+ def listLess(a: Seq[Implicant], b: Seq[Implicant]): Boolean =
+ b.nonEmpty && (a.isEmpty || a.head < b.head || a.head == b.head && listLess(a.tail, b.tail))
ca < cb || ca == cb && listLess(a.sortWith(_ < _), b.sortWith(_ < _))
}
@@ -216,8 +221,14 @@ object QMCMinimizer extends Minimizer {
// extract decode table to inputs and outputs
val (inputs, outputs) = table.table.unzip
- require(outputs.map(_.getWidth == table.default.getWidth).reduce(_ && _), "All output BitPats and default BitPat must have the same length")
- require(if (inputs.toSeq.length > 1) inputs.tail.map(_.width == inputs.head.width).reduce(_ && _) else true, "All input BitPats must have the same length")
+ require(
+ outputs.map(_.getWidth == table.default.getWidth).reduce(_ && _),
+ "All output BitPats and default BitPat must have the same length"
+ )
+ require(
+ if (inputs.toSeq.length > 1) inputs.tail.map(_.width == inputs.head.width).reduce(_ && _) else true,
+ "All input BitPats must have the same length"
+ )
// make sure no two inputs specified in the truth table intersect
for (t <- inputs.tails; if t.nonEmpty)
@@ -234,9 +245,11 @@ object QMCMinimizer extends Minimizer {
val outputBp = BitPat("b" + "?" * (m - i - 1) + "1" + "?" * i)
// Minterms, implicants that makes the output to be 1
- val mint: Seq[Implicant] = table.table.filter { case (_, t) => t.mask.testBit(i) && t.value.testBit(i) }.map(_._1).map(toImplicant)
+ val mint: Seq[Implicant] =
+ table.table.filter { case (_, t) => t.mask.testBit(i) && t.value.testBit(i) }.map(_._1).map(toImplicant)
// Maxterms, implicants that makes the output to be 0
- val maxt: Seq[Implicant] = table.table.filter { case (_, t) => t.mask.testBit(i) && !t.value.testBit(i) }.map(_._1).map(toImplicant)
+ val maxt: Seq[Implicant] =
+ table.table.filter { case (_, t) => t.mask.testBit(i) && !t.value.testBit(i) }.map(_._1).map(toImplicant)
// Don't cares, implicants that can produce either 0 or 1 as output
val dc: Seq[Implicant] = table.table.filter { case (_, t) => !t.mask.testBit(i) }.map(_._1).map(toImplicant)
@@ -251,16 +264,14 @@ object QMCMinimizer extends Minimizer {
implicants.foreach(_.isPrime = true)
val cols = (0 to n).reverse.map(b => implicants.filter(b == _.bp.mask.bitCount))
- val mergeTable = cols.map(
- c => (0 to n).map(
- b => collection.mutable.Set(c.filter(b == _.bp.value.bitCount):_*)
- )
- )
+ val mergeTable = cols.map(c => (0 to n).map(b => collection.mutable.Set(c.filter(b == _.bp.value.bitCount): _*)))
// O(n ^ 3)
for (i <- 0 to n) {
for (j <- 0 until n - i) {
- mergeTable(i)(j).foreach(a => mergeTable(i + 1)(j) ++= mergeTable(i)(j + 1).filter(_ similar a).map(_ merge a))
+ mergeTable(i)(j).foreach(a =>
+ mergeTable(i + 1)(j) ++= mergeTable(i)(j + 1).filter(_.similar(a)).map(_.merge(a))
+ )
}
if (defaultToDc) {
for (j <- 0 until n - i) {
@@ -268,14 +279,14 @@ object QMCMinimizer extends Minimizer {
if (a.bp.mask.testBit(i) && !a.bp.value.testBit(i)) {
// this bit is `0`
val t = new BitPat(a.bp.value.setBit(i), a.bp.mask, a.width)
- if (!maxt.exists(_.intersects(t))) mergeTable(i + 1)(j) += t merge a
+ if (!maxt.exists(_.intersects(t))) mergeTable(i + 1)(j) += t.merge(a)
}
}
for (a <- mergeTable(i)(j + 1).filter(_.isPrime)) {
if (a.bp.mask.testBit(i) && a.bp.value.testBit(i)) {
// this bit is `1`
val t = new BitPat(a.bp.value.clearBit(i), a.bp.mask, a.width)
- if (!maxt.exists(_.intersects(t))) mergeTable(i + 1)(j) += a merge t
+ if (!maxt.exists(_.intersects(t))) mergeTable(i + 1)(j) += a.merge(t)
}
}
}
@@ -288,20 +299,29 @@ object QMCMinimizer extends Minimizer {
val (essentialPrimeImplicants, nonessentialPrimeImplicants, uncoveredImplicants) =
getEssentialPrimeImplicants(primeImplicants, implicants)
- (essentialPrimeImplicants ++ getCover(nonessentialPrimeImplicants, uncoveredImplicants)).map(a => (a.bp, outputBp))
+ (essentialPrimeImplicants ++ getCover(nonessentialPrimeImplicants, uncoveredImplicants)).map(a =>
+ (a.bp, outputBp)
+ )
})
- minimized.tail.foldLeft(table.copy(table = Seq(minimized.head))) { case (tb, t) =>
- if (tb.table.exists(x => x._1 == t._1)) {
- tb.copy(table = tb.table.map { case (k, v) =>
- if (k == t._1) {
- def ones(bitPat: BitPat) = bitPat.rawString.zipWithIndex.collect{case ('1', x) => x}
- (k, BitPat("b" + (0 until v.getWidth).map(i => if ((ones(v) ++ ones(t._2)).contains(i)) "1" else "?").mkString))
- } else (k, v)
- })
- } else {
- tb.copy(table = tb.table :+ t)
- }
+ minimized.tail.foldLeft(table.copy(table = Seq(minimized.head))) {
+ case (tb, t) =>
+ if (tb.table.exists(x => x._1 == t._1)) {
+ tb.copy(table = tb.table.map {
+ case (k, v) =>
+ if (k == t._1) {
+ def ones(bitPat: BitPat) = bitPat.rawString.zipWithIndex.collect { case ('1', x) => x }
+ (
+ k,
+ BitPat(
+ "b" + (0 until v.getWidth).map(i => if ((ones(v) ++ ones(t._2)).contains(i)) "1" else "?").mkString
+ )
+ )
+ } else (k, v)
+ })
+ } else {
+ tb.copy(table = tb.table :+ t)
+ }
}
}
-} \ No newline at end of file
+}
diff --git a/src/main/scala/chisel3/util/experimental/decode/TruthTable.scala b/src/main/scala/chisel3/util/experimental/decode/TruthTable.scala
index 322466f9..e742fd66 100644
--- a/src/main/scala/chisel3/util/experimental/decode/TruthTable.scala
+++ b/src/main/scala/chisel3/util/experimental/decode/TruthTable.scala
@@ -13,10 +13,11 @@ sealed class TruthTable private (val table: Seq[(BitPat, BitPat)], val default:
def writeRow(map: (BitPat, BitPat)): String =
s"${map._1.rawString}->${map._2.rawString}"
- (table.map(writeRow) ++ Seq(s"${" "*(inputWidth + 2)}${default.rawString}")).mkString("\n")
+ (table.map(writeRow) ++ Seq(s"${" " * (inputWidth + 2)}${default.rawString}")).mkString("\n")
}
- def copy(table: Seq[(BitPat, BitPat)] = this.table, default: BitPat = this.default, sort: Boolean = this.sort) = TruthTable(table, default, sort)
+ def copy(table: Seq[(BitPat, BitPat)] = this.table, default: BitPat = this.default, sort: Boolean = this.sort) =
+ TruthTable(table, default, sort)
override def equals(y: Any): Boolean = {
y match {
@@ -27,27 +28,36 @@ sealed class TruthTable private (val table: Seq[(BitPat, BitPat)], val default:
}
object TruthTable {
+
/** Convert a table and default output into a [[TruthTable]]. */
def apply(table: Iterable[(BitPat, BitPat)], default: BitPat, sort: Boolean = true): TruthTable = {
require(table.map(_._1.getWidth).toSet.size == 1, "input width not equal.")
require(table.map(_._2.getWidth).toSet.size == 1, "output width not equal.")
val outputWidth = table.map(_._2.getWidth).head
- val mergedTable = table.groupBy(_._1.toString).map { case (key, values) =>
- // merge same input inputs.
- values.head._1 -> BitPat(s"b${
- Seq.tabulate(outputWidth) { i =>
- val outputSet = values.map(_._2)
- .map(_.rawString)
- .map(_ (i))
- .toSet
- .filterNot(_ == '?')
- require(outputSet.size != 2, s"TruthTable conflict in :\n${values.map { case (i, o) => s"${i.rawString}->${o.rawString}" }.mkString("\n")}")
- outputSet.headOption.getOrElse('?')
- }.mkString
- }")
- }.toSeq
+ val mergedTable = table
+ .groupBy(_._1.toString)
+ .map {
+ case (key, values) =>
+ // merge same input inputs.
+ values.head._1 -> BitPat(s"b${Seq
+ .tabulate(outputWidth) { i =>
+ val outputSet = values
+ .map(_._2)
+ .map(_.rawString)
+ .map(_(i))
+ .toSet
+ .filterNot(_ == '?')
+ require(
+ outputSet.size != 2,
+ s"TruthTable conflict in :\n${values.map { case (i, o) => s"${i.rawString}->${o.rawString}" }.mkString("\n")}"
+ )
+ outputSet.headOption.getOrElse('?')
+ }
+ .mkString}")
+ }
+ .toSeq
import BitPat.bitPatOrder
- new TruthTable(if(sort) mergedTable.sorted else mergedTable, default, sort)
+ new TruthTable(if (sort) mergedTable.sorted else mergedTable, default, sort)
}
/** Parse TruthTable from its string representation. */
@@ -77,10 +87,17 @@ object TruthTable {
BitPat(s"b${bitPat.rawString.zipWithIndex.filter(b => indexes.contains(b._2)).map(_._1).mkString}")
def tableFilter(indexes: Seq[Int]): Option[(TruthTable, Seq[Int])] = {
- if(indexes.nonEmpty) Some((TruthTable(
- table.table.map { case (in, out) => in -> bpFilter(out, indexes) },
- bpFilter(table.default, indexes)
- ), indexes)) else None
+ if (indexes.nonEmpty)
+ Some(
+ (
+ TruthTable(
+ table.table.map { case (in, out) => in -> bpFilter(out, indexes) },
+ bpFilter(table.default, indexes)
+ ),
+ indexes
+ )
+ )
+ else None
}
def index(bitPat: BitPat, bpType: Char): Seq[Int] =
@@ -99,7 +116,12 @@ object TruthTable {
tables: Seq[(TruthTable, Seq[Int])]
): TruthTable = {
def reIndex(bitPat: BitPat, table: TruthTable, indexes: Seq[Int]): Seq[(Char, Int)] =
- table.table.map(a => a._1.toString -> a._2).collectFirst{ case (k, v) if k == bitPat.toString => v}.getOrElse(BitPat.dontCare(indexes.size)).rawString.zip(indexes)
+ table.table
+ .map(a => a._1.toString -> a._2)
+ .collectFirst { case (k, v) if k == bitPat.toString => v }
+ .getOrElse(BitPat.dontCare(indexes.size))
+ .rawString
+ .zip(indexes)
def bitPat(indexedChar: Seq[(Char, Int)]) = BitPat(s"b${indexedChar
.sortBy(_._2)
.map(_._1)
diff --git a/src/main/scala/chisel3/util/experimental/decode/decoder.scala b/src/main/scala/chisel3/util/experimental/decode/decoder.scala
index e0bf83b2..4feda672 100644
--- a/src/main/scala/chisel3/util/experimental/decode/decoder.scala
+++ b/src/main/scala/chisel3/util/experimental/decode/decoder.scala
@@ -3,13 +3,14 @@
package chisel3.util.experimental.decode
import chisel3._
-import chisel3.experimental.{ChiselAnnotation, annotate}
-import chisel3.util.{BitPat, pla}
-import chisel3.util.experimental.{BitSet, getAnnotations}
+import chisel3.experimental.{annotate, ChiselAnnotation}
+import chisel3.util.{pla, BitPat}
+import chisel3.util.experimental.{getAnnotations, BitSet}
import firrtl.annotations.Annotation
import logger.LazyLogging
object decoder extends LazyLogging {
+
/** Use a specific [[Minimizer]] to generated decoded signals.
*
* @param minimizer specific [[Minimizer]], can be [[QMCMinimizer]] or [[EspressoMinimizer]].
@@ -71,7 +72,8 @@ object decoder extends LazyLogging {
qmc(input, truthTable)
}
- try espresso(input, truthTable) catch {
+ try espresso(input, truthTable)
+ catch {
case EspressoNotFoundException =>
logger.error(s"espresso is not found in your PATH:\n${sys.env("PATH").split(":").mkString("\n")}".stripMargin)
qmcFallBack(input, truthTable)
@@ -81,7 +83,6 @@ object decoder extends LazyLogging {
}
}
-
/** Generate a decoder circuit that matches the input to each bitSet.
*
* The resulting circuit functions like the following but is optimized with a logic minifier.
@@ -104,9 +105,7 @@ object decoder extends LazyLogging {
{
bitSets.zipWithIndex.flatMap {
case (bs, i) =>
- bs.terms.map(bp =>
- s"${bp.rawString}->${if (errorBit) "0"}${"0" * (bitSets.size - i - 1)}1${"0" * i}"
- )
+ bs.terms.map(bp => s"${bp.rawString}->${if (errorBit) "0"}${"0" * (bitSets.size - i - 1)}1${"0" * i}")
} ++ Seq(s"${if (errorBit) "1"}${"?" * bitSets.size}")
}.mkString("\n")
)
diff --git a/src/main/scala/chisel3/util/experimental/getAnnotations.scala b/src/main/scala/chisel3/util/experimental/getAnnotations.scala
index dc9b75ee..ac6e6bd1 100644
--- a/src/main/scala/chisel3/util/experimental/getAnnotations.scala
+++ b/src/main/scala/chisel3/util/experimental/getAnnotations.scala
@@ -4,6 +4,7 @@ import chisel3.internal.Builder
import firrtl.AnnotationSeq
object getAnnotations {
+
/** Returns the global Annotations */
def apply(): AnnotationSeq = Builder.annotationSeq
}
diff --git a/src/main/scala/chisel3/util/experimental/group.scala b/src/main/scala/chisel3/util/experimental/group.scala
index e43115d0..202c95d8 100644
--- a/src/main/scala/chisel3/util/experimental/group.scala
+++ b/src/main/scala/chisel3/util/experimental/group.scala
@@ -3,7 +3,7 @@
package chisel3.util.experimental
import chisel3._
-import chisel3.experimental.{ChiselAnnotation, RunFirrtlTransform, annotate}
+import chisel3.experimental.{annotate, ChiselAnnotation, RunFirrtlTransform}
import chisel3.internal.requireIsHardware
import firrtl.Transform
import firrtl.transforms.{GroupAnnotation, GroupComponents}
@@ -46,12 +46,14 @@ object group {
* @tparam T Parent type of input components
*/
def apply[T <: Data](
- components: Seq[T],
- newModule: String,
- newInstance: String,
- outputSuffix: Option[String] = None,
- inputSuffix: Option[String] = None
- )(implicit compileOptions: CompileOptions): Unit = {
+ components: Seq[T],
+ newModule: String,
+ newInstance: String,
+ outputSuffix: Option[String] = None,
+ inputSuffix: Option[String] = None
+ )(
+ implicit compileOptions: CompileOptions
+ ): Unit = {
if (compileOptions.checkSynthesizable) {
components.foreach { data =>
requireIsHardware(data, s"Component ${data.toString} is marked to group, but is not bound.")
@@ -64,4 +66,3 @@ object group {
})
}
}
-