Skip to content

Commit

Permalink
Rename scanLeft/RightOr, switch to impl from rocket-chip and more doc…
Browse files Browse the repository at this point in the history
…umentation
  • Loading branch information
CircuitCoder authored and sequencer committed Mar 7, 2022
1 parent 9c3cb80 commit 08fced3
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,7 @@ import chiseltest.formal._
import org.scalatest.flatspec.AnyFlatSpec
import scala.math.min

// Copied from rocket-core
object RocketImpl {
// Fill 1s from low bits to high bits
def leftOR(x: UInt): UInt = leftOR(x, x.getWidth, x.getWidth)
def leftOR(x: UInt, width: Integer, cap: Integer = 999999): UInt = {
val stop = min(width, cap)
def helper(s: Int, x: UInt): UInt =
if (s >= stop) x else helper(s+s, x | (x << s)(width-1,0))
helper(1, x)(width-1, 0)
}

// Fill 1s form high bits to low bits
def rightOR(x: UInt): UInt = rightOR(x, x.getWidth, x.getWidth)
def rightOR(x: UInt, width: Integer, cap: Integer = 999999): UInt = {
val stop = min(width, cap)
def helper(s: Int, x: UInt): UInt =
if (s >= stop) x else helper(s+s, x | (x >> s))
helper(1, x)(width-1, 0)
}
}

class LSBOrTestModule(width: Int) extends Module {
class scanLeftOrTestModule(width: Int) extends Module {
val input = IO(Input(UInt(width.W)))

var lsb = false.B
Expand All @@ -39,35 +18,31 @@ class LSBOrTestModule(width: Int) extends Module {
cur
}
val ref = VecInit(vec).asUInt
val rocketRef = RocketImpl.leftOR(input)

val testee = LSBOr(input)
val testee = scanLeftOr(input)

assert(testee === ref)
assert(testee === rocketRef)
}

class MSBOrTestModule(width: Int) extends Module {
class scanRightOrTestModule(width: Int) extends Module {
val input = IO(Input(UInt(width.W)))

val ref = Reverse(LSBOr(Reverse(input)))
val rocketRef = RocketImpl.rightOR(input)
val testee = MSBOr(input)
val ref = Reverse(scanLeftOr(Reverse(input)))
val testee = scanRightOr(input)

assert(testee === ref)
assert(testee === rocketRef)
}

class LSBMSBOrTest extends AnyFlatSpec with ChiselScalatestTester with Formal {
"LSBOr" should "correctly computes" in {
class scanOrTest extends AnyFlatSpec with ChiselScalatestTester with Formal {
"scanLeftOr" should "correctly computes" in {
for(i <- 1 to 16) {
verify(new LSBOrTestModule(i), Seq(BoundedCheck(1)))
verify(new scanLeftOrTestModule(i), Seq(BoundedCheck(1)))
}
}

"MSBOr" should "correctly computes" in {
"scanRightOr" should "correctly computes" in {
for(i <- 1 to 16) {
verify(new MSBOrTestModule(i), Seq(BoundedCheck(1)))
verify(new scanRightOrTestModule(i), Seq(BoundedCheck(1)))
}
}
}
41 changes: 21 additions & 20 deletions src/main/scala/chisel3/experimental/util/algorithm/Bitwise.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,43 @@ package chisel3.experimental.util.algorithm

import chisel3._

/** Map each bits to logical or of itself and all bits less siginificant than it.
/** Map each bits to logical or of itself and all bits with lower index.
* Here 'left' means 'with lower index', as in arrays and lists, not to be confused with the 'left' as in 'shift left'
* @example {{{
* LSBOr("b00001000".U) // Returns "b11111000".U
* LSBOr("b00010100".U) // Returns "b11111100".U
* LSBOr("b00000000".U) // Returns "b00000000".U
* scanLeftOr("b00001000".U) // Returns "b11111000".U
* scanLeftOr("b00010100".U) // Returns "b11111100".U
* scanLeftOr("b00000000".U) // Returns "b00000000".U
* }}}
* This circuit seems to be high fan out, but synthesis tool should handle this.
*/
object LSBOr {
object scanLeftOr {
def apply(data: UInt): UInt = {
val width = data.widthOption match {
case Some(w) => w
case None => throw new IllegalArgumentException("Cannot call LSBOr on data with unknown width.")
case None => throw new IllegalArgumentException("Cannot call scanLeftOr on data with unknown width.")
}
VecInit(Seq.tabulate(width) { i: Int =>
VecInit(data.asBools().dropRight(width - i - 1)).asUInt().orR()
}).asUInt()

def helper(s: Int, x: UInt): UInt =
if (s >= width) x else helper(s + s, x | (x << s)(width - 1, 0))
helper(1, data)(width - 1, 0)
}
}

/** Map each bits to logical or of itself and all bits more siginificant than it.
/** Map each bits to logical or of itself and all bits with higher index.
* Here 'right' means 'with higher index', as in arrays and lists, not to be confused with the 'right' as in 'shift right'
* @example {{{
* MSBOr("b00001000".U) // Returns "b00001111".U
* MSBOr("b00010100".U) // Returns "b00011111".U
* MSBOr("b00000000".U) // Returns "b00000000".U
* scanRightOr("b00001000".U) // Returns "b00001111".U
* scanRightOr("b00010100".U) // Returns "b00011111".U
* scanRightOr("b00000000".U) // Returns "b00000000".U
* }}}
* This circuit seems to be high fan out, but synthesis tool should handle this.
*/
object MSBOr {
object scanRightOr {
def apply(data: UInt): UInt = {
val width = data.widthOption match {
case Some(w) => w
case None => throw new IllegalArgumentException("Cannot call MSBOr on data with unknown width.")
case None => throw new IllegalArgumentException("Cannot call scanRightOr on data with unknown width.")
}
VecInit(Seq.tabulate(width) { i: Int =>
VecInit(data.asBools().drop(i)).asUInt().orR()
}).asUInt()
def helper(s: Int, x: UInt): UInt =
if (s >= width) x else helper(s + s, x | (x >> s))
helper(1, data)(width - 1, 0)
}
}

0 comments on commit 08fced3

Please sign in to comment.