diff options
Diffstat (limited to 'src/test/scala/chiselTests/Direction.scala')
| -rw-r--r-- | src/test/scala/chiselTests/Direction.scala | 145 |
1 files changed, 129 insertions, 16 deletions
diff --git a/src/test/scala/chiselTests/Direction.scala b/src/test/scala/chiselTests/Direction.scala index 0c657273..ddbd99d2 100644 --- a/src/test/scala/chiselTests/Direction.scala +++ b/src/test/scala/chiselTests/Direction.scala @@ -4,9 +4,12 @@ package chiselTests import org.scalatest._ import chisel3._ +import chisel3.experimental.OpaqueType import chisel3.stage.ChiselStage import org.scalatest.matchers.should.Matchers +import scala.collection.immutable.SeqMap + class DirectionedBundle extends Bundle { val in = Input(UInt(32.W)) val out = Output(UInt(32.W)) @@ -83,15 +86,15 @@ class DirectionSpec extends ChiselPropSpec with Matchers with Utils { }) } - property("Empty Vecs with no direction on the sample_element *should* cause direction errors") { - an[Exception] should be thrownBy extractCause[Exception] { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val foo = Input(UInt(8.W)) - val x = Vec(0, UInt(8.W)) - }) + property( + "Empty Vecs with no direction on the sample_element should not cause direction errors, as Chisel and chisel3 directions are merged" + ) { + ChiselStage.elaborate(new Module { + val io = IO(new Bundle { + val foo = Input(UInt(8.W)) + val x = Vec(0, UInt(8.W)) }) - } + }) } property("Empty Bundles should not cause direction errors") { @@ -117,15 +120,15 @@ class DirectionSpec extends ChiselPropSpec with Matchers with Utils { }) } - property("Explicitly directioned but empty Bundles should cause direction errors") { - an[Exception] should be thrownBy extractCause[Exception] { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val foo = UInt(8.W) - val x = Input(new Bundle {}) - }) + property( + "Explicitly directioned but empty Bundles should not cause direction errors because Chisel and chisel3 directionality are merged" + ) { + ChiselStage.elaborate(new Module { + val io = IO(new Bundle { + val foo = UInt(8.W) + val x = Input(new Bundle {}) }) - } + }) } import chisel3.experimental.{DataMirror, Direction} @@ -327,4 +330,114 @@ class DirectionSpec extends ChiselPropSpec with Matchers with Utils { } } } + property("Can now describe a Decoupled bundle using Flipped, not Input/Output in chisel3") { + class Decoupled extends Bundle { + val bits = UInt(3.W) + val valid = Bool() + val ready = Flipped(Bool()) + } + class MyModule extends RawModule { + val incoming = IO(Flipped(new Decoupled)) + val outgoing = IO(new Decoupled) + + outgoing <> incoming + } + + val emitted: String = ChiselStage.emitChirrtl(new MyModule) + + // Check that emitted directions are correct. + assert(emitted.contains("input incoming : { bits : UInt<3>, valid : UInt<1>, flip ready : UInt<1>}")) + assert(emitted.contains("output outgoing : { bits : UInt<3>, valid : UInt<1>, flip ready : UInt<1>}")) + assert(emitted.contains("outgoing <= incoming")) + } + property("Can now mix Input/Output and Flipped within the same bundle") { + class Decoupled extends Bundle { + val bits = UInt(3.W) + val valid = Bool() + val ready = Flipped(Bool()) + } + class DecoupledAndMonitor extends Bundle { + val producer = new Decoupled() + val consumer = Flipped(new Decoupled()) + val monitor = Input(new Decoupled()) // Same as Flipped(stripFlipsIn(..)) + val driver = Output(new Decoupled()) // Same as stripFlipsIn(..) + } + class MyModule extends RawModule { + val io = IO(Flipped(new DecoupledAndMonitor())) + io.consumer <> io.producer + io.monitor.bits := io.driver.bits + io.monitor.valid := io.driver.valid + io.monitor.ready := io.driver.ready + } + + val emitted: String = ChiselStage.emitChirrtl(new MyModule) + + assert( + emitted.contains( + "input io : { producer : { bits : UInt<3>, valid : UInt<1>, flip ready : UInt<1>}, flip consumer : { bits : UInt<3>, valid : UInt<1>, flip ready : UInt<1>}, flip monitor : { bits : UInt<3>, valid : UInt<1>, ready : UInt<1>}, driver : { bits : UInt<3>, valid : UInt<1>, ready : UInt<1>}}" + ) + ) + assert(emitted.contains("io.consumer <= io.producer")) + assert(emitted.contains("io.monitor.bits <= io.driver.bits")) + assert(emitted.contains("io.monitor.valid <= io.driver.valid")) + assert(emitted.contains("io.monitor.ready <= io.driver.ready")) + } + property("Bugfix: marking Vec fields with mixed directionality as Output/Input clears inner directions") { + class Decoupled extends Bundle { + val bits = UInt(3.W) + val valid = Bool() + val ready = Flipped(Bool()) + } + class Coercing extends Bundle { + val source = Output(Vec(1, new Decoupled())) + val sink = Input(Vec(1, new Decoupled())) + } + class MyModule extends RawModule { + val io = IO(new Coercing()) + val source = IO(Output(Vec(1, new Decoupled()))) + val sink = IO(Input(Vec(1, new Decoupled()))) + } + + val emitted: String = ChiselStage.emitChirrtl(new MyModule) + + assert( + emitted.contains( + "output io : { source : { bits : UInt<3>, valid : UInt<1>, ready : UInt<1>}[1], flip sink : { bits : UInt<3>, valid : UInt<1>, ready : UInt<1>}[1]}" + ) + ) + assert( + emitted.contains( + "output source : { bits : UInt<3>, valid : UInt<1>, ready : UInt<1>}[1]" + ) + ) + assert( + emitted.contains( + "input sink : { bits : UInt<3>, valid : UInt<1>, ready : UInt<1>}[1]" + ) + ) + } + property("Bugfix: clearing all flips inside an opaque type") { + + class Decoupled extends Bundle { + val bits = UInt(3.W) + val valid = Bool() + val ready = Flipped(Bool()) + } + class MyOpaqueType extends Record with OpaqueType { + val k = new Decoupled() + val elements = SeqMap("" -> k) + override def cloneType: this.type = (new MyOpaqueType).asInstanceOf[this.type] + } + class MyModule extends RawModule { + val w = Wire(new MyOpaqueType()) + } + + val emitted: String = ChiselStage.emitChirrtl(new MyModule) + + assert( + emitted.contains( + "wire w : { bits : UInt<3>, valid : UInt<1>, flip ready : UInt<1>}" + ) + ) + } } |
