summaryrefslogtreecommitdiff
path: root/src/test/scala/chiselTests
diff options
context:
space:
mode:
authorKamyar Mohajerani2021-10-05 18:12:57 -0400
committerGitHub2021-10-05 22:12:57 +0000
commitbdba21b032e592b21d117a8d68f166ba3834c205 (patch)
tree9aa57806c313fe3685b2f386406e81de76a6953d /src/test/scala/chiselTests
parentc2985aa6ef95a45d6ce9663a17f835eaba0cb9c5 (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 'src/test/scala/chiselTests')
-rw-r--r--src/test/scala/chiselTests/UIntOps.scala84
1 files changed, 84 insertions, 0 deletions
diff --git a/src/test/scala/chiselTests/UIntOps.scala b/src/test/scala/chiselTests/UIntOps.scala
index 62d00de2..bc6454b8 100644
--- a/src/test/scala/chiselTests/UIntOps.scala
+++ b/src/test/scala/chiselTests/UIntOps.scala
@@ -6,6 +6,7 @@ import chisel3._
import org.scalatest._
import chisel3.stage.ChiselStage
import chisel3.testers.BasicTester
+import chisel3.util._
import org.scalacheck.Shrink
import org.scalatest.matchers.should.Matchers
@@ -22,6 +23,8 @@ class UIntOps extends Module {
val modout = Output(UInt(32.W))
val lshiftout = Output(UInt(32.W))
val rshiftout = Output(UInt(32.W))
+ val lrotateout = Output(UInt(32.W))
+ val rrotateout = Output(UInt(32.W))
val lessout = Output(Bool())
val greatout = Output(Bool())
val eqout = Output(Bool())
@@ -30,6 +33,8 @@ class UIntOps extends Module {
val greateqout = Output(Bool())
})
+ dontTouch(io)
+
val a = io.a
val b = io.b
@@ -42,6 +47,8 @@ class UIntOps extends Module {
io.modout := a % b
io.lshiftout := (a << b(3, 0))(31, 0)
io.rshiftout := a >> b
+ io.lrotateout := a.rotateLeft(5)
+ io.rrotateout := a.rotateRight(5)
io.lessout := a < b
io.greatout := a > b
io.eqout := a === b
@@ -67,6 +74,14 @@ class UIntOpsTester(a: Long, b: Long) extends BasicTester {
assert(dut.io.modout === (a % (b max 1)).U(32.W))
assert(dut.io.lshiftout === (a << (b % 16)).U(32.W))
assert(dut.io.rshiftout === (a >> b).U(32.W))
+ assert(
+ dut.io.lrotateout === s"h${Integer.rotateLeft(a.toInt, 5).toHexString}"
+ .U(32.W)
+ )
+ assert(
+ dut.io.rrotateout === s"h${Integer.rotateRight(a.toInt, 5).toHexString}"
+ .U(32.W)
+ )
assert(dut.io.lessout === (a < b).B)
assert(dut.io.greatout === (a > b).B)
assert(dut.io.eqout === (a == b).B)
@@ -98,6 +113,65 @@ class NegativeShift(t: => Bits) extends Module {
Reg(t) >> -1
}
+class BasicRotate extends BasicTester {
+ val shiftAmount = random.LFSR(4)
+ val ctr = RegInit(0.U(4.W))
+
+
+ val rotL = 1.U(3.W).rotateLeft(shiftAmount)
+ val rotR = 1.U(3.W).rotateRight(shiftAmount)
+
+ printf("Shift amount: %d rotateLeft:%b rotateRight:%b\n", shiftAmount, rotL, rotR)
+
+ switch(shiftAmount % 3.U) {
+ is(0.U, 3.U) {
+ assert(rotL === "b001".U)
+ assert(rotR === "b001".U)
+ }
+ is(1.U) {
+ assert(rotL === "b010".U)
+ assert(rotR === "b100".U)
+ }
+ is(2.U) {
+ assert(rotL === "b100".U)
+ assert(rotR === "b010".U)
+ }
+ }
+
+ ctr := ctr + 1.U
+
+ when (ctr === 15.U){
+ stop()
+ }
+}
+
+/** rotating a w-bit word left by n should be equivalent to rotating it by w - n
+ * to the left
+ */
+class MatchedRotateLeftAndRight(w: Int = 13) extends BasicTester {
+ val initValue = BigInt(w, scala.util.Random)
+ println(s"Initial value: ${initValue.toString(2)}")
+
+ val maxWidthBits = log2Ceil(w + 1)
+ val shiftAmount1 = RegInit(0.U(w.W))
+ val shiftAmount2 = RegInit(w.U(w.W))
+ shiftAmount1 := shiftAmount1 + 1.U
+ shiftAmount2 := shiftAmount2 - 1.U
+
+ val value = RegInit(initValue.U(w.W))
+
+ val out1 = value.rotateLeft(shiftAmount1)
+ val out2 = value.rotateRight(shiftAmount2)
+
+ printf("rotateLeft by %d: %b\n", shiftAmount1, out1)
+
+ assert(out1 === out2)
+ when(shiftAmount1 === w.U) {
+ assert(out1 === initValue.U)
+ stop()
+ }
+}
+
class UIntLitExtractTester extends BasicTester {
assert("b101010".U(2) === false.B)
assert("b101010".U(3) === true.B)
@@ -140,6 +214,16 @@ class UIntOpsSpec extends ChiselPropSpec with Matchers with Utils {
}
}
+ property("rotateLeft and rotateRight should work for dynamic shift values") {
+ assertTesterPasses(new BasicRotate)
+ }
+
+ property(
+ "rotateLeft and rotateRight should be consistent for dynamic shift values"
+ ) {
+ assertTesterPasses(new MatchedRotateLeftAndRight)
+ }
+
property("Bit extraction on literals should work for all non-negative indices") {
assertTesterPasses(new UIntLitExtractTester)
}