@@ -185,25 +185,34 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi
185
185
*
186
186
* @example
187
187
* {{{
188
- * myBits = 0x5 = 0b101
189
- * myBits(1,0) => 0b01 // extracts the two least significant bits
188
+ * val myBits = "0b101".U
189
+ * myBits(1, 0) // "0b01".U // extracts the two least significant bits
190
+ *
191
+ * // Note that zero-width ranges are also legal
192
+ * myBits(-1, 0) // 0.U(0.W) // zero-width UInt
190
193
* }}}
191
194
* @param x the high bit
192
195
* @param y the low bit
193
- * @return a hardware component contain the requested bits
196
+ * @return a hardware component containing the requested bits
194
197
*/
195
198
final def apply (x : Int , y : Int ): UInt = macro SourceInfoTransform .xyArg
196
199
197
200
/** @group SourceInfoTransformMacro */
198
201
final def do_apply (x : Int , y : Int )(implicit sourceInfo : SourceInfo ): UInt = {
199
- if (x < y || y < 0 ) {
200
- Builder .error(s " Invalid bit range ( $x, $y) " )
202
+ if ((x < y && ! (x == - 1 && y == 0 )) || y < 0 ) {
203
+ val zeroWidthSuggestion =
204
+ if (x == y - 1 ) {
205
+ s " . If you are trying to extract zero-width range, right-shift by 'lo' before extracting. "
206
+ } else {
207
+ " "
208
+ }
209
+ Builder .error(s " Invalid bit range [hi= $x, lo= $y] $zeroWidthSuggestion" )
201
210
}
202
- val w = x - y + 1
211
+ val resultWidth = x - y + 1
203
212
// This preserves old behavior while a more more consistent API is under debate
204
213
// See https://github.com/freechipsproject/chisel3/issues/867
205
214
litOption.map { value =>
206
- ((value >> y) & ((BigInt (1 ) << w ) - 1 )).asUInt(w .W )
215
+ ((value >> y) & ((BigInt (1 ) << resultWidth ) - 1 )).asUInt(resultWidth .W )
207
216
}.getOrElse {
208
217
requireIsHardware(this , " bits to be sliced" )
209
218
@@ -214,21 +223,28 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi
214
223
case _ =>
215
224
}
216
225
217
- pushOp(DefPrim (sourceInfo, UInt (Width (w)), BitsExtractOp , this .ref, ILit (x), ILit (y)))
226
+ // FIRRTL does not yet support empty extraction so we must return the zero-width wire here:
227
+ if (resultWidth == 0 ) {
228
+ 0 .U (0 .W )
229
+ } else {
230
+ pushOp(DefPrim (sourceInfo, UInt (Width (resultWidth)), BitsExtractOp , this .ref, ILit (x), ILit (y)))
231
+ }
218
232
}
219
233
}
220
234
221
- // REVIEW TODO: again, is this necessary? Or just have this and use implicits?
222
235
/** Returns a subset of bits on this $coll from `hi` to `lo` (inclusive), statically addressed.
223
236
*
224
237
* @example
225
238
* {{{
226
- * myBits = 0x5 = 0b101
227
- * myBits(1,0) => 0b01 // extracts the two least significant bits
239
+ * val myBits = "0b101".U
240
+ * myBits(1, 0) // "0b01".U // extracts the two least significant bits
241
+ *
242
+ * // Note that zero-width ranges are also legal
243
+ * myBits(-1, 0) // 0.U(0.W) // zero-width UInt
228
244
* }}}
229
245
* @param x the high bit
230
246
* @param y the low bit
231
- * @return a hardware component contain the requested bits
247
+ * @return a hardware component containing the requested bits
232
248
*/
233
249
final def apply (x : BigInt , y : BigInt ): UInt = macro SourceInfoTransform .xyArg
234
250
0 commit comments