summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiuyang Liu2021-09-07 14:14:47 +0800
committerGitHub2021-09-07 14:14:47 +0800
commit9964857e2ddd97fc14ac63d1a8a04223a19a15c3 (patch)
tree0fe70f239e7adf2412127a86d5c0cbd6b01ee96e
parent7cd821f5a975ff97694d39893af1d89952d37c69 (diff)
parent189da9828b1990e360fe521598dc340a260d05d5 (diff)
Merge pull request #2113 from yqszxx/fix-pla-dcto1
Fix a bug causes incorrect pla generation when input is `?`
-rw-r--r--src/main/scala/chisel3/util/pla.scala39
-rw-r--r--src/test/scala/chiselTests/util/experimental/PlaSpec.scala15
2 files changed, 41 insertions, 13 deletions
diff --git a/src/main/scala/chisel3/util/pla.scala b/src/main/scala/chisel3/util/pla.scala
index bb2b7996..c57ca962 100644
--- a/src/main/scala/chisel3/util/pla.scala
+++ b/src/main/scala/chisel3/util/pla.scala
@@ -17,6 +17,20 @@ object pla {
* a `1` means this product term makes the function value to `1`
* and a `0` or `?` means this product term make the function value to `0`
*
+ * @note There is one special case which we call it `? -> 1`. In this scenario, for some of the output functions (bits),
+ * all input terms that make this function value to `1` is purely composed by `?`. In a real pla, this will result in
+ * no connection to the gates in the AND Plane (verilog `z` on gate inputs), which in turn makes the outputs of the
+ * AND Plane undetermined (verilog `x` on outputs). This is not desired behavior in most cases, for example the
+ * minimization result of following truth table:
+ * 0 -> 1
+ * 1 -> 1
+ * which is:
+ * ? -> 1
+ * actually means something other than a verilog `x`. To ease the generation of minimized truth tables, this pla
+ * generation api will hard wire outputs to a `1` on this special case.
+ * This behavior is formally described as: if product terms that make one function value to `1` is solely consisted
+ * of don't-cares (`?`s), then this function is implemented as a constant `1`.
+ *
* @param table A [[Seq]] of inputs -> outputs mapping
* @param invert A [[BitPat]] specify which bit of the output should be inverted. `1` means the correspond position
* of the output should be inverted in the PLA, a `0` or a `?` means direct output from the OR matrix.
@@ -68,20 +82,19 @@ object pla {
// the AND matrix
// use `term -> AND line` map to reuse AND matrix output lines
val andMatrixOutputs: Map[String, Bool] = inputTerms.map { t =>
- t.toString -> Cat(
- Seq
- .tabulate(numberOfInputs) { i =>
- if (t.mask.testBit(i)) {
- Some(
- if (t.value.testBit(i)) inputs(i)
- else invInputs(i)
- )
- } else {
- None
- }
+ val andMatrixInput = Seq
+ .tabulate(numberOfInputs) { i =>
+ if (t.mask.testBit(i)) {
+ Some(
+ if (t.value.testBit(i)) inputs(i)
+ else invInputs(i)
+ )
+ } else {
+ None
}
- .flatten
- ).andR()
+ }
+ .flatten
+ if (andMatrixInput.nonEmpty) t.toString -> Cat(andMatrixInput).andR() else t.toString -> true.B
}.toMap
// the OR matrix
diff --git a/src/test/scala/chiselTests/util/experimental/PlaSpec.scala b/src/test/scala/chiselTests/util/experimental/PlaSpec.scala
index 45ac012e..8af5c936 100644
--- a/src/test/scala/chiselTests/util/experimental/PlaSpec.scala
+++ b/src/test/scala/chiselTests/util/experimental/PlaSpec.scala
@@ -49,6 +49,21 @@ class PlaSpec extends ChiselFlatSpec {
})
}
+ "#2112" should "be generated correctly" in {
+ assertTesterPasses(new BasicTester {
+ val table = Seq(
+ (BitPat("b000"), BitPat("b?01")),
+ (BitPat("b111"), BitPat("b?01")),
+ )
+ table.foreach { case (i, o) =>
+ val (plaIn, plaOut) = pla(table)
+ plaIn := WireDefault(i.value.U(3.W))
+ chisel3.assert(o === plaOut, "Input " + i.toString + " produced incorrect output BitPat(%b)", plaOut)
+ }
+ stop()
+ })
+ }
+
"A simple PLA" should "be generated correctly" in {
assertTesterPasses(new BasicTester {
val table = Seq(