diff options
Diffstat (limited to 'src')
6 files changed, 274 insertions, 4 deletions
diff --git a/src/main/scala/chisel3/internal/firrtl/Emitter.scala b/src/main/scala/chisel3/internal/firrtl/Emitter.scala index 2f1b75b0..3d10670e 100644 --- a/src/main/scala/chisel3/internal/firrtl/Emitter.scala +++ b/src/main/scala/chisel3/internal/firrtl/Emitter.scala @@ -27,7 +27,9 @@ private class Emitter(circuit: Circuit) { private def emitType(d: Data, clearDir: Boolean = false): String = d match { // scalastyle:ignore cyclomatic.complexity line.size.limit case d: Clock => "Clock" - case d: EnumType => s"UInt${d.width}" + case _: AsyncReset => "AsyncReset" + case _: ResetType => "Reset" + case d: chisel3.core.EnumType => s"UInt${d.width}" case d: UInt => s"UInt${d.width}" case d: SInt => s"SInt${d.width}" case d: FixedPoint => s"Fixed${d.width}${d.binaryPoint}" diff --git a/src/test/scala/chiselTests/AsyncResetSpec.scala b/src/test/scala/chiselTests/AsyncResetSpec.scala new file mode 100644 index 00000000..78a29e99 --- /dev/null +++ b/src/test/scala/chiselTests/AsyncResetSpec.scala @@ -0,0 +1,172 @@ +// See LICENSE for license details. + +package chiselTests + +import chisel3._ +import chisel3.util.{Counter, Queue} +import chisel3.testers.BasicTester +import firrtl.checks.CheckResets.NonLiteralAsyncResetValueException + +class AsyncResetTester extends BasicTester { + val (_, cDiv) = Counter(true.B, 4) + // First rising edge when count === 3 + val slowClk = cDiv.asClock + + val (count, done) = Counter(true.B, 16) + + val asyncResetNext = RegInit(false.B) + asyncResetNext := count === 4.U + val asyncReset = asyncResetNext.asAsyncReset + + val reg = withClockAndReset(slowClk, asyncReset) { + RegInit(123.U(8.W)) + } + reg := 5.U // Normal connection + + when (count === 3.U) { + assert(reg === 5.U) + } + when (count >= 5.U && count < 7.U) { + assert(reg === 123.U) + } .elsewhen (count >= 7.U) { + assert(reg === 5.U) + } + + when (done) { + stop() + } +} + +class AsyncResetAggregateTester extends BasicTester { + class MyBundle extends Bundle { + val x = UInt(8.W) + val y = UInt(8.W) + } + val (_, cDiv) = Counter(true.B, 4) + // First rising edge when count === 3 + val slowClk = cDiv.asClock + + val (count, done) = Counter(true.B, 16) + + val asyncResetNext = RegInit(false.B) + asyncResetNext := count === 4.U + val asyncReset = asyncResetNext.asAsyncReset + + val reg = withClockAndReset(slowClk, asyncReset) { + val init = Wire(Vec(2, new MyBundle)) + init(0).x := 0.U + init(0).y := 0.U + init(1).x := 0.U + init(1).y := 0.U + RegInit(init) + } + reg(0).x := 5.U // Normal connections + reg(0).y := 6.U + reg(1).x := 7.U + reg(1).y := 8.U + + when (count === 3.U) { + assert(reg(0).x === 5.U) + assert(reg(0).y === 6.U) + assert(reg(1).x === 7.U) + assert(reg(1).y === 8.U) + } + when (count >= 5.U && count < 7.U) { + assert(reg(0).x === 0.U) + assert(reg(0).y === 0.U) + assert(reg(1).x === 0.U) + assert(reg(1).y === 0.U) + } .elsewhen (count >= 7.U) { + assert(reg(0).x === 5.U) + assert(reg(0).y === 6.U) + assert(reg(1).x === 7.U) + assert(reg(1).y === 8.U) + } + + when (done) { + stop() + } +} + +class AsyncResetQueueTester extends BasicTester { + val (_, cDiv) = Counter(true.B, 4) + val slowClk = cDiv.asClock + + val (count, done) = Counter(true.B, 16) + + val asyncResetNext = RegNext(false.B, false.B) + val asyncReset = asyncResetNext.asAsyncReset + + val queue = withClockAndReset (slowClk, asyncReset) { + Module(new Queue(UInt(8.W), 4)) + } + queue.io.enq.valid := true.B + queue.io.enq.bits := count + + queue.io.deq.ready := false.B + + val doCheck = RegNext(false.B, false.B) + when (queue.io.count === 3.U) { + asyncResetNext := true.B + doCheck := true.B + } + when (doCheck) { + assert(queue.io.count === 0.U) + } + + when (done) { + stop() + } +} + +class AsyncResetSpec extends ChiselFlatSpec { + + behavior of "AsyncReset" + + it should "be allowed with literal reset values" in { + elaborate(new BasicTester { + withReset(reset.asAsyncReset)(RegInit(123.U)) + }) + } + + it should "NOT be allowed with non-literal reset values" in { + a [NonLiteralAsyncResetValueException] shouldBe thrownBy { + compile(new BasicTester { + val x = WireInit(123.U + 456.U) + withReset(reset.asAsyncReset)(RegInit(x)) + }) + } + } + + it should "NOT be allowed to connect directly to a Bool" in { + a [ChiselException] shouldBe thrownBy { + elaborate(new BasicTester { + val bool = Wire(Bool()) + val areset = reset.asAsyncReset + bool := areset + }) + } + } + + it should "simulate correctly" in { + assertTesterPasses(new AsyncResetTester) + } + + it should "simulate correctly with aggregates" in { + assertTesterPasses(new AsyncResetAggregateTester) + } + + it should "allow casting to and from Bool" in { + elaborate(new BasicTester { + val r: Reset = reset + val a: AsyncReset = WireInit(r.asAsyncReset) + val b: Bool = a.asBool + val c: AsyncReset = b.asAsyncReset + }) + } + + it should "allow changing the reset type of whole modules like Queue" in { + assertTesterPasses(new AsyncResetQueueTester) + } + +} diff --git a/src/test/scala/chiselTests/CloneModuleSpec.scala b/src/test/scala/chiselTests/CloneModuleSpec.scala index 59ba2eb5..ca8bd007 100644 --- a/src/test/scala/chiselTests/CloneModuleSpec.scala +++ b/src/test/scala/chiselTests/CloneModuleSpec.scala @@ -9,7 +9,7 @@ import chisel3.testers.BasicTester class MultiIOQueue[T <: Data](gen: T, val entries: Int) extends MultiIOModule { val clk = IO(Input(Clock())) - val rst = IO(Input(Bool())) + val rst = IO(Input(Reset())) val enq = IO(Flipped(EnqIO(gen))) val deq = IO(Flipped(DeqIO(gen))) val count = IO(Output(UInt(log2Ceil(entries + 1).W))) @@ -28,7 +28,7 @@ class QueueClone(multiIO: Boolean = false) extends Module { q1.rst := reset q1.enq <> io.enq q2_io("clk").asInstanceOf[Clock] := clock - q2_io("rst").asInstanceOf[Bool] := reset + q2_io("rst").asInstanceOf[Reset] := reset q2_io("enq").asInstanceOf[q1.enq.type] <> q1.deq io.deq <> q2_io("deq").asInstanceOf[q1.deq.type] io.count := q1.count + q2_io("count").asInstanceOf[q1.count.type] diff --git a/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala b/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala index 861b3fdd..4ca7dcda 100644 --- a/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala +++ b/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala @@ -243,5 +243,51 @@ class CompatibiltyInteroperabilitySpec extends ChiselFlatSpec { } } } + + "Compatibility Modules" should "have Bool as their reset type" in { + compile { + import Chisel._ + class Intf extends Bundle { + val in = Bool(INPUT) + val en = Bool(INPUT) + val out = Bool(OUTPUT) + } + class Child extends Module { + val io = new Intf + io.out := Mux(io.en, io.in, reset) + } + new Module { + val io = new Intf + val child = Module(new Child) + io <> child.io + } + } + } + + "Compatibility Modules" should "be instantiable inside chisel3 Modules" in { + compile { + object Compat { + import Chisel._ + class Intf extends Bundle { + val in = Input(UInt(8.W)) + val out = Output(UInt(8.W)) + } + class OldMod extends Module { + val io = IO(new Intf) + io.out := Reg(next = io.in) + } + } + import chisel3._ + import Compat._ + new Module { + val io = IO(new Intf) + io <> Module(new Module { + val io = IO(new Intf) + val inst = Module(new OldMod) + io <> inst.io + }).io + } + } + } } diff --git a/src/test/scala/chiselTests/ResetSpec.scala b/src/test/scala/chiselTests/ResetSpec.scala new file mode 100644 index 00000000..297c5516 --- /dev/null +++ b/src/test/scala/chiselTests/ResetSpec.scala @@ -0,0 +1,50 @@ +// See LICENSE for license details. + +package chiselTests + +import chisel3._ +import chisel3.experimental.{IO, RawModule} +import chisel3.util.{Counter, Queue} +import chisel3.testers.BasicTester + +class ResetAgnosticModule extends RawModule { + val clk = IO(Input(Clock())) + val rst = IO(Input(Reset())) + val out = IO(Output(UInt(8.W))) + + val reg = withClockAndReset(clk, rst)(RegInit(0.U(8.W))) + reg := reg + 1.U + out := reg +} + + +class ResetSpec extends ChiselFlatSpec { + + behavior of "Reset" + + it should "allow writing modules that are reset agnostic" in { + val sync = compile(new Module { + val io = IO(new Bundle { + val out = Output(UInt(8.W)) + }) + val inst = Module(new ResetAgnosticModule) + inst.clk := clock + inst.rst := reset + assert(inst.rst.isInstanceOf[chisel3.ResetType]) + io.out := inst.out + }) + sync should include ("always @(posedge clk)") + + val async = compile(new Module { + val io = IO(new Bundle { + val out = Output(UInt(8.W)) + }) + val inst = Module(new ResetAgnosticModule) + inst.clk := clock + inst.rst := reset.asTypeOf(AsyncReset()) + assert(inst.rst.isInstanceOf[chisel3.ResetType]) + io.out := inst.out + }) + async should include ("always @(posedge clk or posedge rst)") + } +} diff --git a/src/test/scala/examples/SimpleVendingMachine.scala b/src/test/scala/examples/SimpleVendingMachine.scala index 4bb6027a..2021ece8 100644 --- a/src/test/scala/examples/SimpleVendingMachine.scala +++ b/src/test/scala/examples/SimpleVendingMachine.scala @@ -52,7 +52,7 @@ class VerilogVendingMachine extends BlackBox { // Because this is a blackbox, we must explicity add clock and reset val io = IO(new SimpleVendingMachineIO { val clock = Input(Clock()) - val reset = Input(Bool()) + val reset = Input(Reset()) }) } |
