diff options
Diffstat (limited to 'src')
5 files changed, 78 insertions, 20 deletions
diff --git a/src/main/scala/chisel3/util/BitPat.scala b/src/main/scala/chisel3/util/BitPat.scala index 985d22da..0dcb2466 100644 --- a/src/main/scala/chisel3/util/BitPat.scala +++ b/src/main/scala/chisel3/util/BitPat.scala @@ -58,6 +58,22 @@ object BitPat { */ def dontCare(width: Int): BitPat = BitPat("b" + ("?" * width)) + /** Creates a [[BitPat]] of all 1 of the specified bitwidth. + * + * @example {{{ + * val myY = BitPat.Y(4) // equivalent to BitPat("b1111") + * }}} + */ + def Y(width: Int = 1): BitPat = BitPat("b" + ("1" * width)) + + /** Creates a [[BitPat]] of all 0 of the specified bitwidth. + * + * @example {{{ + * val myN = BitPat.N(4) // equivalent to BitPat("b0000") + * }}} + */ + def N(width: Int = 1): BitPat = BitPat("b" + ("0" * width)) + /** Allows BitPats to be used where a UInt is expected. * * @note the BitPat must not have don't care bits (will error out otherwise) @@ -106,9 +122,11 @@ object BitPat { */ sealed class BitPat(val value: BigInt, val mask: BigInt, width: Int) extends SourceInfoDoc { def getWidth: Int = width + def apply(x: Int): BitPat = macro SourceInfoTransform.xArg + def apply(x: Int, y: Int): BitPat = macro SourceInfoTransform.xyArg def === (that: UInt): Bool = macro SourceInfoTransform.thatArg def =/= (that: UInt): Bool = macro SourceInfoTransform.thatArg - + def ## (that: BitPat): BitPat = macro SourceInfoTransform.thatArg override def equals(obj: Any): Boolean = { obj match { case y: BitPat => value == y.value && mask == y.mask && getWidth == y.getWidth @@ -117,6 +135,18 @@ sealed class BitPat(val value: BigInt, val mask: BigInt, width: Int) extends Sou } /** @group SourceInfoTransformMacro */ + def do_apply(x: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): BitPat = { + do_apply(x, x) + } + + /** @group SourceInfoTransformMacro */ + def do_apply(x: Int, y: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): BitPat = { + require(width > x && y >= 0, s"Invalid bit range ($x, $y), index should be bounded by (${width - 1}, 0)") + require(x >= y, s"Invalid bit range ($x, $y), x should be greater or equal to y.") + BitPat(s"b${rawString.slice(width - x - 1, width - y)}") + } + + /** @group SourceInfoTransformMacro */ def do_=== (that: UInt) (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = { value.asUInt === (that & mask.asUInt) @@ -126,12 +156,19 @@ sealed class BitPat(val value: BigInt, val mask: BigInt, width: Int) extends Sou (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = { !(this === that) } - - override def toString = { - "BitPat(" + - (0 until width).map(i => - if (((mask >> i) & 1) == 1) if (((value >> i) & 1) == 1) "1" else "0" else "?" - ).reverse.reduce(_ + _) + - ")" + /** @group SourceInfoTransformMacro */ + def do_##(that: BitPat)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): BitPat = { + new BitPat((value << that.getWidth) + that.value, (mask << that.getWidth) + that.mask, this.width + that.getWidth) } + + /** Generate raw string of a BitPat. */ + def rawString: String = Seq.tabulate(width) { i => + (value.testBit(width - i - 1), mask.testBit(width - i - 1)) match { + case (true, true) => "1" + case (false, true) => "0" + case (_, false) => "?" + } + }.mkString + + override def toString = s"BitPat($rawString)" } diff --git a/src/main/scala/chisel3/util/experimental/decode/EspressoMinimizer.scala b/src/main/scala/chisel3/util/experimental/decode/EspressoMinimizer.scala index 3ecec048..1d725875 100644 --- a/src/main/scala/chisel3/util/experimental/decode/EspressoMinimizer.scala +++ b/src/main/scala/chisel3/util/experimental/decode/EspressoMinimizer.scala @@ -18,7 +18,7 @@ object EspressoMinimizer extends Minimizer with LazyLogging { .replace('1', '0') .replace('t', '1') val defaultType: Char = { - val t = table.default.toString.drop(7).dropRight(1).toCharArray.distinct + val t = table.default.rawString.toCharArray.distinct require(t.length == 1, "Internal Error: espresso only accept unified default type.") t.head } diff --git a/src/main/scala/chisel3/util/experimental/decode/QMCMinimizer.scala b/src/main/scala/chisel3/util/experimental/decode/QMCMinimizer.scala index 54faa734..c1533f44 100644 --- a/src/main/scala/chisel3/util/experimental/decode/QMCMinimizer.scala +++ b/src/main/scala/chisel3/util/experimental/decode/QMCMinimizer.scala @@ -286,7 +286,7 @@ object QMCMinimizer extends Minimizer { 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.toString.drop(7).dropRight(1).zipWithIndex.collect{case ('1', x) => x} + 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) }) diff --git a/src/main/scala/chisel3/util/experimental/decode/TruthTable.scala b/src/main/scala/chisel3/util/experimental/decode/TruthTable.scala index f4f200ce..683de16b 100644 --- a/src/main/scala/chisel3/util/experimental/decode/TruthTable.scala +++ b/src/main/scala/chisel3/util/experimental/decode/TruthTable.scala @@ -12,9 +12,9 @@ final class TruthTable(val table: Map[BitPat, BitPat], val default: BitPat) { override def toString: String = { def writeRow(map: (BitPat, BitPat)): String = - s"${TruthTable.bpStr(map._1)}->${TruthTable.bpStr(map._2)}" + s"${map._1.rawString}->${map._2.rawString}" - (table.map(writeRow) ++ Seq(s"${" "*(inputWidth + 2)}${TruthTable.bpStr(default)}")).toSeq.sorted.mkString("\n") + (table.map(writeRow) ++ Seq(s"${" "*(inputWidth + 2)}${default.rawString}")).toSeq.sorted.mkString("\n") } def copy(table: Map[BitPat, BitPat] = this.table, default: BitPat = this.default) = new TruthTable(table, default) @@ -51,11 +51,11 @@ object TruthTable { values.head._1 -> BitPat(s"b${ Seq.tabulate(outputWidth) { i => val outputSet = values.map(_._2) - .map(bpStr) + .map(_.rawString) .map(_ (i)) .toSet .filterNot(_ == '?') - require(outputSet.size != 2, s"TruthTable conflict in :\n${values.map { case (i, o) => s"${bpStr(i)}->${bpStr(o)}" }.mkString("\n")}") + 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 }") @@ -74,7 +74,7 @@ object TruthTable { table: TruthTable ): Seq[(TruthTable, Seq[Int])] = { def bpFilter(bitPat: BitPat, indexes: Seq[Int]): BitPat = - BitPat(s"b${bpStr(bitPat).zipWithIndex.filter(b => indexes.contains(b._2)).map(_._1).mkString}") + 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( @@ -84,7 +84,7 @@ object TruthTable { } def index(bitPat: BitPat, bpType: Char): Seq[Int] = - bpStr(bitPat).zipWithIndex.filter(_._1 == bpType).map(_._2) + bitPat.rawString.zipWithIndex.filter(_._1 == bpType).map(_._2) Seq('1', '0', '?').flatMap(t => tableFilter(index(table.default, t))) } @@ -99,7 +99,7 @@ object TruthTable { tables: Seq[(TruthTable, Seq[Int])] ): TruthTable = { def reIndex(bitPat: BitPat, table: TruthTable, indexes: Seq[Int]): Seq[(Char, Int)] = - bpStr(table.table.map(a => a._1.toString -> a._2).getOrElse(bitPat.toString, BitPat.dontCare(indexes.size))).zip(indexes) + (table.table.map(a => a._1.toString -> a._2).getOrElse(bitPat.toString, BitPat.dontCare(indexes.size))).rawString.zip(indexes) def bitPat(indexedChar: Seq[(Char, Int)]) = BitPat(s"b${indexedChar .sortBy(_._2) .map(_._1) @@ -111,9 +111,7 @@ object TruthTable { key -> bitPat(tables.flatMap { case (table, indexes) => reIndex(key, table, indexes) }) } .toMap, - bitPat(tables.flatMap { case (table, indexes) => bpStr(table.default).zip(indexes) }) + bitPat(tables.flatMap { case (table, indexes) => table.default.rawString.zip(indexes) }) ) } - - private def bpStr(bitPat: BitPat) = bitPat.toString.drop(7).dropRight(1) } diff --git a/src/test/scala/chiselTests/util/BitPatSpec.scala b/src/test/scala/chiselTests/util/BitPatSpec.scala index ca8dd85c..0c83493f 100644 --- a/src/test/scala/chiselTests/util/BitPatSpec.scala +++ b/src/test/scala/chiselTests/util/BitPatSpec.scala @@ -15,7 +15,30 @@ class BitPatSpec extends AnyFlatSpec with Matchers { BitPat("b" + testPattern).toString should be (s"BitPat($testPattern)") } + it should "convert a BitPat to raw form" in { + val testPattern = "0" * 32 + "1" * 32 + "?" * 32 + "?01" * 32 + BitPat("b" + testPattern).rawString should be(testPattern) + } + it should "not fail if BitPat width is 0" in { intercept[IllegalArgumentException]{BitPat("b")} } + + it should "contact BitPat via ##" in { + (BitPat.Y(4) ## BitPat.dontCare(3) ## BitPat.N(2)).toString should be (s"BitPat(1111???00)") + } + + it should "index and return new BitPat" in { + val b = BitPat("b1001???") + b(0) should be(BitPat.dontCare(1)) + b(6) should be(BitPat.Y()) + b(5) should be(BitPat.N()) + } + + it should "slice and return new BitPat" in { + val b = BitPat("b1001???") + b(2, 0) should be(BitPat("b???")) + b(4, 3) should be(BitPat("b01")) + b(6, 6) should be(BitPat("b1")) + } } |
