diff options
| author | Kamyar Mohajerani | 2021-10-05 18:12:57 -0400 |
|---|---|---|
| committer | GitHub | 2021-10-05 22:12:57 +0000 |
| commit | bdba21b032e592b21d117a8d68f166ba3834c205 (patch) | |
| tree | 9aa57806c313fe3685b2f386406e81de76a6953d /core/src/main/scala/chisel3 | |
| parent | c2985aa6ef95a45d6ce9663a17f835eaba0cb9c5 (diff) | |
Circular-shift (rotate) operations for UInt (#1140)
* change static shift behavior to mod width when width is known
* add dynamic shift
* basic tests that actually do something
* MatchedRotateLeftAndRight based on the idea from @chick
* BasicRotate rotate "b001" and compare with known values
* Fix check for KnownWidth(0|1) as suggested by @aswaterman
* Add dontTouch to UIntOps.io (other tests were also optimized out)
Co-authored-by: Chick Markley <chick@qrhino.com>
Co-authored-by: Andrew Waterman <andrew@sifive.com>
Diffstat (limited to 'core/src/main/scala/chisel3')
| -rw-r--r-- | core/src/main/scala/chisel3/Bits.scala | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/core/src/main/scala/chisel3/Bits.scala b/core/src/main/scala/chisel3/Bits.scala index b7a4a1a7..a96d2732 100644 --- a/core/src/main/scala/chisel3/Bits.scala +++ b/core/src/main/scala/chisel3/Bits.scala @@ -650,6 +650,51 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U override def do_>> (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = binop(sourceInfo, UInt(this.width), DynamicShiftRightOp, that) + /** + * Circular shift to the left + * @param that number of bits to rotate + * @return UInt of same width rotated left n bits + */ + final def rotateLeft(that: Int): UInt = macro SourceInfoWhiteboxTransform.thatArg + + def do_rotateLeft(n: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = width match { + case _ if (n == 0) => this + case KnownWidth(w) if (w <= 1) => this + case KnownWidth(w) if n >= w => do_rotateLeft(n % w) + case _ if (n < 0) => do_rotateRight(-n) + case _ => tail(n) ## head(n) + } + + /** + * Circular shift to the right + * @param that number of bits to rotate + * @return UInt of same width rotated right n bits + */ + final def rotateRight(that: Int): UInt = macro SourceInfoWhiteboxTransform.thatArg + + def do_rotateRight(n: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = width match { + case _ if (n <= 0) => do_rotateLeft(-n) + case KnownWidth(w) if (w <= 1) => this + case KnownWidth(w) if n >= w => do_rotateRight(n % w) + case _ => this(n - 1, 0) ## (this >> n) + } + + final def rotateRight(that: UInt): UInt = macro SourceInfoWhiteboxTransform.thatArg + + private def dynamicShift(n: UInt, staticShift: (UInt,Int) => UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) : UInt = + n.asBools().zipWithIndex.foldLeft(this){ + case (in, (en, sh)) => Mux(en, staticShift(in, 1 << sh), in) + } + + def do_rotateRight(n: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + dynamicShift(n, _ rotateRight _) + + final def rotateLeft(that: UInt): UInt = macro SourceInfoWhiteboxTransform.thatArg + + def do_rotateLeft(n: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + dynamicShift(n, _ rotateLeft _) + + /** Conditionally set or clear a bit * * @param off a dynamic offset |
