1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
// SPDX-License-Identifier: Apache-2.0
package chisel3.util
import scala.language.experimental.macros
import chisel3._
import chisel3.internal.chiselRuntimeDeprecated
import chisel3.internal.sourceinfo.{SourceInfo, SourceInfoTransform}
object BitPat {
/** Parses a bit pattern string into (bits, mask, width).
*
* @return bits the literal value, with don't cares being 0
* @return mask the mask bits, with don't cares being 0 and cares being 1
* @return width the number of bits in the literal, including values and
* don't cares, but not including the white space and underscores
*/
private def parse(x: String): (BigInt, BigInt, Int) = {
// Notes:
// While Verilog Xs also handle octal and hex cases, there isn't a
// compelling argument and no one has asked for it.
// If ? parsing is to be exposed, the return API needs further scrutiny
// (especially with things like mask polarity).
require(x.head == 'b', "BitPats must be in binary and be prefixed with 'b'")
require(x.length > 1, "BitPat width cannot be 0.")
var bits = BigInt(0)
var mask = BigInt(0)
var count = 0
for (d <- x.tail) {
if (! (d == '_' || d.isWhitespace)) {
require("01?".contains(d), "Literal: " + x + " contains illegal character: " + d)
mask = (mask << 1) + (if (d == '?') 0 else 1)
bits = (bits << 1) + (if (d == '1') 1 else 0)
count += 1
}
}
(bits, mask, count)
}
/** Creates a [[BitPat]] literal from a string.
*
* @param n the literal value as a string, in binary, prefixed with 'b'
* @note legal characters are '0', '1', and '?', as well as '_' and white
* space (which are ignored)
*/
def apply(n: String): BitPat = {
val (bits, mask, width) = parse(n)
new BitPat(bits, mask, width)
}
/** Creates a [[BitPat]] of all don't cares of the specified bitwidth.
*
* @example {{{
* val myDontCare = BitPat.dontCare(4) // equivalent to BitPat("b????")
* }}}
*/
def dontCare(width: Int): BitPat = BitPat("b" + ("?" * 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)
*/
def bitPatToUInt(x: BitPat): UInt = {
require(x.mask == (BigInt(1) << x.getWidth) - 1)
x.value.asUInt(x.getWidth.W)
}
/** Allows UInts to be used where a BitPat is expected, useful for when an
* interface is defined with BitPats but not all cases need the partial
* matching capability.
*
* @note the UInt must be a literal
*/
def apply(x: UInt): BitPat = {
val len = if (x.isWidthKnown) x.getWidth else 0
apply("b" + x.litValue.toString(2).reverse.padTo(len, "0").reverse.mkString)
}
implicit class fromUIntToBitPatComparable(x: UInt) extends SourceInfoDoc {
import internal.sourceinfo.{SourceInfo, SourceInfoTransform}
import scala.language.experimental.macros
final def === (that: BitPat): Bool = macro SourceInfoTransform.thatArg
final def =/= (that: BitPat): Bool = macro SourceInfoTransform.thatArg
/** @group SourceInfoTransformMacro */
def do_=== (that: BitPat)
(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = that === x
/** @group SourceInfoTransformMacro */
def do_=/= (that: BitPat)
(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = that =/= x
}
}
/** Bit patterns are literals with masks, used to represent values with don't
* care bits. Equality comparisons will ignore don't care bits.
*
* @example {{{
* "b10101".U === BitPat("b101??") // evaluates to true.B
* "b10111".U === BitPat("b101??") // evaluates to true.B
* "b10001".U === BitPat("b101??") // evaluates to false.B
* }}}
*/
sealed class BitPat(val value: BigInt, val mask: BigInt, width: Int) extends SourceInfoDoc {
def getWidth: Int = width
def === (that: UInt): Bool = macro SourceInfoTransform.thatArg
def =/= (that: UInt): Bool = macro SourceInfoTransform.thatArg
override def equals(obj: Any): Boolean = {
obj match {
case y: BitPat => value == y.value && mask == y.mask && getWidth == y.getWidth
case _ => false
}
}
/** @group SourceInfoTransformMacro */
def do_=== (that: UInt)
(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = {
value.asUInt === (that & mask.asUInt)
}
/** @group SourceInfoTransformMacro */
def do_=/= (that: UInt)
(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(_ + _) +
")"
}
}
|