diff --git a/assertion/src/main/scala/assertionTiming/concurrentAssertion.scala b/assertion/src/main/scala/assertionTiming/concurrentAssertion.scala index b7cc4a1..bf947f4 100644 --- a/assertion/src/main/scala/assertionTiming/concurrentAssertion.scala +++ b/assertion/src/main/scala/assertionTiming/concurrentAssertion.scala @@ -19,6 +19,8 @@ import chisel3._ * * @author Victor Alexander Hansen, s194027@student.dtu.dk * @author Niels Frederik Flemming Holm Frandsen, s194053@student.dtu.dk + * + * Works only with registers */ /** assertNever(): @@ -30,7 +32,6 @@ object assertNever { fork { for (i <- 0 until cycles) { assert(!cond(), message) - System.out.println("Test") dut.clock.step(1) } } @@ -46,7 +47,6 @@ object assertAlways { fork { for (i <- 0 until cycles) { assert(cond(), message) - System.out.println("Test") dut.clock.step(1) } } @@ -57,17 +57,28 @@ object assertAlways { * Checks for the argument condition to be true just once within the number of * clock cycles passed, a liveness property. Fails if the condition is not true * at least once within the window of cycles + * + * Must be joined */ object assertEventually { def apply[T <: Module](dut: T, cond: () => Boolean, message: String, cycles: Int) = { + var i = 0 fork { - for (i <- 0 until cycles) { + /*for (i <- 0 until cycles) { if (cond()) { break - } else { + } else if (i == cycles - 1){ + assert(false, message) + } + dut.clock.step(1) + }*/ + while (!cond()) { + if (i == cycles-1) { assert(false, message) } + i += 1 + dut.clock.step(1) } } } @@ -78,12 +89,14 @@ object assertEventually { * clock cycles passed, and hold true until the last cycle. Fails if the * condition is not true at least once within the window of cycles, or if * condition becomes false after it becomes true. + * + * Must be joined */ object assertEventuallyAlways { def apply[T <: Module](dut: T, cond: () => Boolean, message: String, cycles: Int) = { - var k = 0 - for (i <- 0 until cycles) { + var i = 0 + /*for (i <- 0 until cycles) { if (cond()) { break } else { @@ -91,18 +104,29 @@ object assertEventuallyAlways { assert(false, message) } k += 1 - } + }*/ - for (j <- 0 until cycles - k) { - assert(cond(), message) + fork { + while (!cond()) { + if (i == cycles-1) { + assert(false, message) + } + i += 1 + dut.clock.step(1) + } + + for (j <- 0 until cycles - i) { + assert(cond(), message) + dut.clock.step(1) + } } } } /** assertOneHot(): - * checks for one hot encoding violations + * checks if exactly one bit of the expression is high */ -/*object assertOneHot { +object assertOneHot { def apply(cond: UInt, message: String, cycles: Int) { for (i <- 0 until cycles) { @@ -110,4 +134,3 @@ object assertEventuallyAlways { } } } -**/ \ No newline at end of file diff --git a/assertion/src/main/scala/mainClass.scala b/assertion/src/main/scala/mainClass.scala index ff2273b..f12b762 100644 --- a/assertion/src/main/scala/mainClass.scala +++ b/assertion/src/main/scala/mainClass.scala @@ -6,11 +6,14 @@ import concurrent._ // Compiles, but simple test does not yet work class mainClass extends Module { val io = IO(new Bundle { - val s = Input(UInt(4.W)) + val s = Input(Bool()) val c = Output(UInt(4.W)) }) - io.c := io.s + val reg = RegInit(0.U (4.W)) + + reg := Mux(io.s, 4.U, 0.U) + io.c := reg //conAssert(true.B, "Error", 10) } diff --git a/assertion/src/test/scala/concurrentAssertionTest.scala b/assertion/src/test/scala/concurrentAssertionTest.scala index 394f564..9127d6b 100644 --- a/assertion/src/test/scala/concurrentAssertionTest.scala +++ b/assertion/src/test/scala/concurrentAssertionTest.scala @@ -6,28 +6,161 @@ import chiseltest._ class concurrentAssertionTest extends FlatSpec with ChiselScalatestTester with Matchers { behavior of "The mainClass" - it should "test an assertion to always be true" in { +// assertAlways + it should "test assertAlways" in { test(new mainClass()) { dut => { - dut.io.s.poke(4.U) + dut.io.s.poke(true.B) + dut.clock.step(1) + assertAlways(dut, () => dut.io.c.peek.litValue == 4, "Error", 20) + } + } + } + + it should "test that assertAlways fails when poking false" in { + test(new mainClass()) { + dut => { + + dut.io.s.poke(true.B) dut.clock.step(1) val t = assertAlways(dut, () => dut.io.c.peek.litValue == 4, "Error", 20) + + dut.clock.step(10) + dut.io.s.poke(false.B) + dut.clock.step(1) + } + } + } + + it should "test time depency of clock cycles" in { + test(new mainClass()) { + dut => { - timescope { - dut.clock.step(1) - dut.io.s.poke(4.U) - System.out.println("Start") - dut.clock.step(1) - } - - timescope { - dut.clock.step(100) - System.out.println("Slut") - //dut.io.s.poke(4.U) - //t.join - } + // Test of assertAlways + dut.io.s.poke(true.B) + dut.clock.step(1) + assertAlways(dut, () => dut.io.c.peek.litValue == 4, "Error", 20) + + dut.clock.step(21) + dut.io.s.poke(false.B) + dut.clock.step(1) + + // Test of assertNever + dut.io.s.poke(false.B) + dut.clock.step(1) + assertNever(dut, () => dut.io.c.peek.litValue == 4, "Error", 40) + + dut.clock.step(41) + dut.io.s.poke(true.B) + dut.clock.step(1) + } + } + } + +// assertNever + it should "test assertNever" in { + test(new mainClass()) { + dut => { + + dut.io.s.poke(false.B) + dut.clock.step(1) + assertNever(dut, () => dut.io.c.peek.litValue == 4, "Error", 20) + } + } + } + + it should "test assertNever fails" in { + test(new mainClass()) { + dut => { + + dut.io.s.poke(false.B) + dut.clock.step(1) + val t = assertNever(dut, () => dut.io.c.peek.litValue == 4, "Error", 20) + + dut.clock.step(15) + dut.io.s.poke(true.B) + dut.clock.step(1) + } + } + } + + //assertEventually + it should "test assertEventually passes, once true regardless of what happens next" in { + test(new mainClass()) { + dut => { + + dut.io.s.poke(false.B) + dut.clock.step(1) + val t = assertEventually(dut, () => dut.io.c.peek.litValue == 4, "Error", 20) + + dut.clock.step(5) + dut.io.s.poke(true.B) + dut.clock.step(1) + dut.io.s.poke(false.B) + t.join + } + } + } + + it should "test assertEventually fails when exceeding clock cycles" in { + test(new mainClass()) { + dut => { + + dut.io.s.poke(false.B) + dut.clock.step(1) + val t = assertEventually(dut, () => dut.io.c.peek.litValue == 4, "Error", 20) + + t.join + } + } + } + + // assertEventuallyAlways + it should "test assertEventuallyAlways pass" in { + test(new mainClass()) { + dut => { + + dut.io.s.poke(false.B) + dut.clock.step(1) + val t = assertEventuallyAlways(dut, () => dut.io.c.peek.litValue == 4, "Error", 20) + + dut.clock.step(1) + dut.io.s.poke(true.B) + + t.join + } + } + } + + it should "fail, if cond does not hold true once true" in { + test(new mainClass()) { + dut => { + + dut.io.s.poke(false.B) + dut.clock.step(1) + val t = assertEventuallyAlways(dut, () => dut.io.c.peek.litValue == 4, "Error", 20) + + dut.clock.step(5) + dut.io.s.poke(true.B) + dut.clock.step(1) + dut.io.s.poke(false.B) + + t.join + } + } + } +} + +/*class concurrentAssertionTest2 extends FlatSpec with ChiselScalatestTester with Matchers { + behavior of "The oneHot" + // assertOneHot + it should "pass if only one bit is high" in { + test(new oneHot()) { + dut => { + + } } } -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/assertion/src/test/scala/timescopeTest.scala b/assertion/src/test/scala/timescopeTest.scala index 744a30e..22376f8 100644 --- a/assertion/src/test/scala/timescopeTest.scala +++ b/assertion/src/test/scala/timescopeTest.scala @@ -9,7 +9,7 @@ class timescopeTest extends FlatSpec with ChiselScalatestTester with Matchers { test(new mainClass()) { dut => { - dut.io.s.poke(4.U) + dut.io.s.poke(true.B) dut.clock.step(1) fork { for (i <- 0 until 20) { @@ -17,11 +17,9 @@ class timescopeTest extends FlatSpec with ChiselScalatestTester with Matchers { dut.clock.step(1) } } - //timescope { - dut.clock.step(10) - dut.io.s.poke(0.U) - //} + dut.clock.step(10) + dut.io.s.poke(false.B) } } } -} \ No newline at end of file +}