From 89679a3c7b42f34d3b9e93dfb6972bc36b6af297 Mon Sep 17 00:00:00 2001 From: Boyang Han Date: Mon, 6 Sep 2021 07:35:46 -0700 Subject: Add a test case to demonstrate the bug found in #2112 --- .../scala/chiselTests/util/experimental/PlaSpec.scala | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/test/scala/chiselTests/util/experimental/PlaSpec.scala b/src/test/scala/chiselTests/util/experimental/PlaSpec.scala index 45ac012e..ced4f9dd 100644 --- a/src/test/scala/chiselTests/util/experimental/PlaSpec.scala +++ b/src/test/scala/chiselTests/util/experimental/PlaSpec.scala @@ -49,6 +49,22 @@ class PlaSpec extends ChiselFlatSpec { }) } + "#2112" should "be generated correctly" in { + assertTesterPasses(new BasicTester { + val table = Seq( + (BitPat("b0"), BitPat("b?0")), + (BitPat("b1"), BitPat("b?1")), + (BitPat("b?"), BitPat("b1?")), + ) + table.foreach { case (i, o) => + val (plaIn, plaOut) = pla(table) + plaIn := WireDefault(i.value.U(3.W)) + chisel3.assert(plaOut === o.value.U(8.W), "Input " + i.toString + " produced incorrect output BitPat(%b)", plaOut) + } + stop() + }) + } + "A simple PLA" should "be generated correctly" in { assertTesterPasses(new BasicTester { val table = Seq( -- cgit v1.2.3 From 0ca4ce23400d3624f8f617aa8ae21880d8430c2e Mon Sep 17 00:00:00 2001 From: Boyang Han Date: Mon, 6 Sep 2021 21:27:51 -0700 Subject: Test case rework --- src/test/scala/chiselTests/util/experimental/PlaSpec.scala | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/test/scala/chiselTests/util/experimental/PlaSpec.scala b/src/test/scala/chiselTests/util/experimental/PlaSpec.scala index ced4f9dd..8af5c936 100644 --- a/src/test/scala/chiselTests/util/experimental/PlaSpec.scala +++ b/src/test/scala/chiselTests/util/experimental/PlaSpec.scala @@ -52,14 +52,13 @@ class PlaSpec extends ChiselFlatSpec { "#2112" should "be generated correctly" in { assertTesterPasses(new BasicTester { val table = Seq( - (BitPat("b0"), BitPat("b?0")), - (BitPat("b1"), BitPat("b?1")), - (BitPat("b?"), BitPat("b1?")), + (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(plaOut === o.value.U(8.W), "Input " + i.toString + " produced incorrect output BitPat(%b)", plaOut) + chisel3.assert(o === plaOut, "Input " + i.toString + " produced incorrect output BitPat(%b)", plaOut) } stop() }) -- cgit v1.2.3 From 189da9828b1990e360fe521598dc340a260d05d5 Mon Sep 17 00:00:00 2001 From: Boyang Han Date: Mon, 6 Sep 2021 21:07:47 -0700 Subject: Fix #2112, handle `?->1` case --- src/main/scala/chisel3/util/pla.scala | 39 +++++++++++++++++++++++------------ 1 file changed, 26 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 -- cgit v1.2.3