question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Circular shift operation

See original GitHub issue

Circular shift or bit rotation (https://en.wikipedia.org/wiki/Circular_shift) is common bit-wise operation in many applications including cryptography. VHDL offers operators ror and rol as well as more polished versions as functions rotate_left and rotate_right for signed and unsigned types. While the user can implement it using bit slicing and concatenation, it could become a little tricky and prone to mistakes. It would be nice to have operators/methods for this in Chisel.

A possible implementation for static rotation is:

  implicit class RotatableUInt(u: UInt) {
    def <<<(x: Int): UInt =
      if (x == 0)
        u
      else if (x > 0) {
        val w = u.getWidth
        u(w - x - 1, 0) ## u(w - 1, w - x)
      }
      else
        this >>> (-x)

    def >>>(x: Int): UInt =
      if (x > 0) {
        val w = u.getWidth
        u(x - 1, 0) ## u(w - 1, x)
      }
      else
        this <<< (-x)

Gotchas:

  • Verilog and C don’t seem to have operators for this operation. Verilog is using >>> operator as sign extension shift.

Type of issue: feature request

Impact: API addition (no impact on existing code)

Development Phase: proposal

Other information

If the current behavior is a bug, please provide the steps to reproduce the problem:

What is the current behavior?

What is the expected behavior?

Please tell us about your environment:

What is the use case for changing the behavior?

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:5 (5 by maintainers)

github_iconTop GitHub Comments

3reactions
aswatermancommented, Jul 27, 2019

I’d avoid the names <<< and >>> like the plague. Not only are they used for arithmetic shifts in Verilog, they’re used for logical shifts in Scala! rotateLeft and rotateRight aren’t too long to type, and they’ll leave no one guessing.

The static rotates can be defined without relying on getWidth, so they can work without knowing the width at elaboration time:

def rotateLeft(n: Int): UInt =
  if (n == 0) this
  else if (n < 0) this.rotateRight(-n)
  else this.tail(n) ## this.head(n)

def rotateRight(n: Int): UInt =
  if (n <= 0) this.rotateLeft(-n)
  else this(n-1, 0)  ## (this >> n)

These will issue an error when the magnitude of n exceeds the width, which is an artificial limitation, but is probably OK in practice. For the special case that the width is known at elaboration time, we could reduce the argument with a modulus.

Supporting dynamic rotates is trickier because of argument reduction on the shift amount, given that we permit non-power-of-2-sized UInts. What does it mean to right-shift a 13-bit-wide UInt by 9711? The correct answer is, of course, that it should be equivalent to right-shifting it by (9711 % 13), or 0. But computing that requires an expensive arithmetic circuit. If you first truncate the rotate amount to 4 bits, you get a different result: (9711 % 16) % 13 is 2.

I would just recommend against defining dynamic rotates, or as a compromise, only define them for known-power-of-2-sized inputs, to save users from shooting themselves in the foot with either poor performance or surprising semantics.

1reaction
aswatermancommented, Jul 28, 2019

I think we need to hear from some other chisel devs about expanding the API, but it would be nice if you prepared the PR (and tests).

I’m fine with not having the special argument-reduction case when the width is known, and I’m also fine with erroring in Firrtl if n is too big. Some other operators behave the same way.

Limiting this to UInt makes sense to me.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Circular shift on the binary representation of an integer by `k ...
The idea is to perform a normal bitwise left or right shift by first isolating the sequence of k–bits from the right or...
Read more >
Circular Shift Right Function - Technology Tutorials
This picture shows the Binary Circular Shift Right Function. You can see that all bits shift to the right, with the LSB (Least...
Read more >
Shift Operations
A rotate operation is a circular shift in which no bits are discarded. A rotate right of the 8 bit binary number 1000...
Read more >
Rotate bits of a number - GeeksforGeeks
Bit Rotation: A rotation (or circular shift) is an operation similar to shift except that the bits that fall off at one end...
Read more >
Shift and rotate bits - Online Tools
Circular shifts, also called rotations, use the bit that got shifted out at one end and inserts it back as the new bit...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found