diff options
| -rw-r--r-- | core/src/main/scala/chisel3/internal/firrtl/Converter.scala | 9 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/Direction.scala | 61 |
2 files changed, 67 insertions, 3 deletions
diff --git a/core/src/main/scala/chisel3/internal/firrtl/Converter.scala b/core/src/main/scala/chisel3/internal/firrtl/Converter.scala index fe95445c..f73e85d2 100644 --- a/core/src/main/scala/chisel3/internal/firrtl/Converter.scala +++ b/core/src/main/scala/chisel3/internal/firrtl/Converter.scala @@ -301,8 +301,11 @@ private[chisel3] object Converter { case d: SInt => fir.SIntType(convert(d.width)) case d: FixedPoint => fir.FixedType(convert(d.width), convert(d.binaryPoint)) case d: Interval => fir.IntervalType(d.range.lowerBound, d.range.upperBound, d.range.firrtlBinaryPoint) - case d: Analog => fir.AnalogType(convert(d.width)) - case d: Vec[_] => fir.VectorType(extractType(d.sample_element, clearDir, info), d.length) + case d: Analog => fir.AnalogType(convert(d.width)) + case d: Vec[_] => + val childClearDir = clearDir || + d.specifiedDirection == SpecifiedDirection.Input || d.specifiedDirection == SpecifiedDirection.Output + fir.VectorType(extractType(d.sample_element, childClearDir, info), d.length) case d: Record => { val childClearDir = clearDir || d.specifiedDirection == SpecifiedDirection.Input || d.specifiedDirection == SpecifiedDirection.Output @@ -316,7 +319,7 @@ private[chisel3] object Converter { if (!d.opaqueType) fir.BundleType(d.elements.toIndexedSeq.reverse.map { case (_, e) => eltField(e) }) else - extractType(d.elements.head._2, true, info) + extractType(d.elements.head._2, childClearDir, info) } } diff --git a/src/test/scala/chiselTests/Direction.scala b/src/test/scala/chiselTests/Direction.scala index 0c657273..03755e83 100644 --- a/src/test/scala/chiselTests/Direction.scala +++ b/src/test/scala/chiselTests/Direction.scala @@ -7,6 +7,8 @@ import chisel3._ 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)) @@ -327,4 +329,63 @@ class DirectionSpec extends ChiselPropSpec with Matchers with Utils { } } } + 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 { + val k = new Decoupled() + val elements = SeqMap("" -> k) + override def opaqueType = elements.size == 1 + 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>}" + ) + ) + } } |
