Skip to content

Commit

Permalink
Optimize TruthTable.split and .merge to do nothing in common case
Browse files Browse the repository at this point in the history
Most TruthTables have a default of all dont care. We can optimize this
common case by doing actual work in TruthTable.split and
TruthTable.merge.
  • Loading branch information
jackkoenig committed Apr 12, 2024
1 parent e9a2c6d commit bb32df4
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 11 deletions.
29 changes: 20 additions & 9 deletions src/main/scala/chisel3/util/experimental/decode/TruthTable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,13 @@ object TruthTable {
def index(bitPat: BitPat, bpType: Char): Seq[Int] =
bitPat.rawString.zipWithIndex.filter(_._1 == bpType).map(_._2)

Seq('1', '0', '?').flatMap(t => tableFilter(index(table.default, t)))
// We need to split if the default has a mix of values (no need to split if all ones, all zeros, or all ?)
val needToSplit = !(table.default.allDontCares || table.default.allZeros || table.default.allOnes)
if (needToSplit) {
Seq('1', '0', '?').flatMap(t => tableFilter(index(table.default, t)))
} else {
Seq(table -> (0 until table.default.width))
}
}

/** consume tables, merge it into single table with different default bits.
Expand All @@ -185,13 +191,18 @@ object TruthTable {
.sortBy(_._2)
.map(_._1)
.mkString}")
TruthTable(
tables
.flatMap(_._1.table.map(_._1))
.map { key =>
key -> bitPat(tables.flatMap { case (table, indexes) => reIndex(key, table, indexes) })
},
bitPat(tables.flatMap { case (table, indexes) => table.default.rawString.zip(indexes) })
)
val needToMerge = tables.size > 1
if (needToMerge) {
TruthTable(
tables
.flatMap(_._1.table.map(_._1))
.map { key =>
key -> bitPat(tables.flatMap { case (table, indexes) => reIndex(key, table, indexes) })
},
bitPat(tables.flatMap { case (table, indexes) => table.default.rawString.zip(indexes) })
)
} else {
tables.head._1
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: Apache-2.0

package chiselTests.util.experimental
package chisel3.util.experimental.decode

import chisel3._
import chisel3.util.BitPat
Expand All @@ -9,7 +9,7 @@ import org.scalatest.flatspec.AnyFlatSpec

class TruthTableSpec extends AnyFlatSpec {
val table = TruthTable(
Map(
Seq(
// BitPat("b000") -> BitPat("b0"),
BitPat("b001") -> BitPat("b?"),
BitPat("b010") -> BitPat("b?"),
Expand Down Expand Up @@ -123,4 +123,23 @@ class TruthTableSpec extends AnyFlatSpec {
|""".stripMargin)
)
}

behavior.of("TruthTable.split")

it should "not change the TruthTable when the default only uses a single value" in {
val result = TruthTable.split(table)
assert(result == Seq(table -> Seq(0)))
// As an optimization, it should return the same literal object
assert(result.head._1 eq table)
}

behavior.of("TruthTable.merge")

it should "not change the TruthTable when merging a single one" in {
val tables = Seq(table -> Seq(0))
val result = TruthTable.merge(tables)
assert(result == table)
// As an optimization, it should return the same literal object
assert(result eq table)
}
}

0 comments on commit bb32df4

Please sign in to comment.