diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 6ba1408562a..8accec62769 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -16,7 +16,13 @@ import chisel3.reflect.DataMirror * of ready or valid. * @param gen the type of data to be wrapped in DecoupledIO */ -class DecoupledIO[+T <: Data](gen: T) extends ReadyValidIO[T](gen) { +class DecoupledIO[+T <: Data](gen: () => T) extends ReadyValidIO[T](gen) { + + @deprecated( + "Use companion object apply to make a Decoupled. Use constructor that takes () => T if extending Decoupled.", + "Chisel 7.9.0" + ) + def this(gen: T) = this(() => gen) /** Applies the supplied functor to the bits of this interface, returning a new * typed DecoupledIO interface. @@ -37,7 +43,7 @@ class DecoupledIO[+T <: Data](gen: T) extends ReadyValidIO[T](gen) { object Decoupled { /** Wraps some Data with a DecoupledIO interface. */ - def apply[T <: Data](gen: T): DecoupledIO[T] = new DecoupledIO(gen) + def apply[T <: Data](gen: T): DecoupledIO[T] = new DecoupledIO(() => gen) // TODO: use a proper empty data type, this is a quick and dirty solution private final class EmptyBundle extends Bundle @@ -58,7 +64,7 @@ object Decoupled { DataMirror.directionOf(irr.bits) == Direction.Output, "Only safe to cast produced Irrevocable bits to Decoupled." ) - val d = Wire(new DecoupledIO(chiselTypeOf(irr.bits))) + val d = Wire(new DecoupledIO(() => chiselTypeOf(irr.bits))) d.bits := irr.bits d.valid := irr.valid irr.ready := d.ready diff --git a/src/main/scala/chisel3/util/Irrevocable.scala b/src/main/scala/chisel3/util/Irrevocable.scala index 098a0bc1c9a..356035d13d4 100644 --- a/src/main/scala/chisel3/util/Irrevocable.scala +++ b/src/main/scala/chisel3/util/Irrevocable.scala @@ -13,11 +13,18 @@ import chisel3.reflect.DataMirror * @param gen the type of data to be wrapped in IrrevocableIO * @groupdesc Signals The actual hardware fields of the Bundle */ -class IrrevocableIO[+T <: Data](gen: T) extends ReadyValidIO[T](gen) +class IrrevocableIO[+T <: Data](gen: () => T) extends ReadyValidIO[T](gen) { + + @deprecated( + "Use companion object apply to make an Irrevocable. Use constructor that takes () => T if extending Irrevocable.", + "Chisel 7.9.0" + ) + def this(gen: T) = this(() => gen) +} /** Factory adds an irrevocable handshaking protocol to a data bundle. */ object Irrevocable { - def apply[T <: Data](gen: T): IrrevocableIO[T] = new IrrevocableIO(gen) + def apply[T <: Data](gen: T): IrrevocableIO[T] = new IrrevocableIO(() => gen) /** Upconverts a DecoupledIO input to an IrrevocableIO, allowing an IrrevocableIO to be used * where a DecoupledIO is expected. @@ -29,7 +36,7 @@ object Irrevocable { DataMirror.directionOf(dec.bits) == Direction.Input, "Only safe to cast consumed Decoupled bits to Irrevocable." ) - val i = Wire(new IrrevocableIO(chiselTypeOf(dec.bits))) + val i = Wire(new IrrevocableIO(() => chiselTypeOf(dec.bits))) dec.bits := i.bits dec.valid := i.valid i.ready := dec.ready diff --git a/src/main/scala/chisel3/util/Queue.scala b/src/main/scala/chisel3/util/Queue.scala index 611a353785d..4b5b11b3e98 100644 --- a/src/main/scala/chisel3/util/Queue.scala +++ b/src/main/scala/chisel3/util/Queue.scala @@ -191,7 +191,7 @@ object Queue { flush: Option[Bool] = None ): DecoupledIO[T] = { if (entries == 0) { - val deq = Wire(new DecoupledIO(chiselTypeOf(enq.bits))) + val deq = Wire(Decoupled(chiselTypeOf(enq.bits))) deq.valid := enq.valid deq.bits := enq.bits enq.ready := deq.ready @@ -325,7 +325,7 @@ object Queue { ): IrrevocableIO[T] = { val deq = apply(enq, entries, pipe, flow, useSyncReadMem, flush) require(entries > 0, "Zero-entry queues don't guarantee Irrevocability") - val irr = Wire(new IrrevocableIO(chiselTypeOf(deq.bits))) + val irr = Wire(Irrevocable(chiselTypeOf(deq.bits))) irr.bits := deq.bits irr.valid := deq.valid deq.ready := irr.ready diff --git a/src/main/scala/chisel3/util/ReadyValidIO.scala b/src/main/scala/chisel3/util/ReadyValidIO.scala index a968ecdb9ed..3561df4b0b6 100644 --- a/src/main/scala/chisel3/util/ReadyValidIO.scala +++ b/src/main/scala/chisel3/util/ReadyValidIO.scala @@ -16,7 +16,10 @@ import chisel3.util.simpleClassName * @param gen the type of data to be wrapped in Ready/Valid * @groupdesc Signals The actual hardware fields of the Bundle */ -abstract class ReadyValidIO[+T <: Data](gen: T) extends Bundle { +abstract class ReadyValidIO[+T <: Data](gen: () => T) extends Bundle { + + @deprecated("Use constructor that takes () => T if extending ReadyValidIO.", "Chisel 7.9.0") + def this(gen: T) = this(() => gen) /** Indicates that the consumer is ready to accept the data this cycle * @group Signals @@ -31,12 +34,12 @@ abstract class ReadyValidIO[+T <: Data](gen: T) extends Bundle { /** The data to be transferred when ready and valid are asserted at the same cycle * @group Signals */ - val bits = Output(gen) + val bits = Output(gen()) /** A stable typeName for this `ReadyValidIO` and any of its implementations * using the supplied `Data` generator's `typeName` */ - override def typeName = s"${simpleClassName(this.getClass)}_${gen.typeName}" + override def typeName = s"${simpleClassName(this.getClass)}_${bits.typeName}" } object ReadyValidIO { diff --git a/src/main/scala/chisel3/util/Valid.scala b/src/main/scala/chisel3/util/Valid.scala index 3a4a2fb182a..1097b92ae1a 100644 --- a/src/main/scala/chisel3/util/Valid.scala +++ b/src/main/scala/chisel3/util/Valid.scala @@ -21,7 +21,13 @@ import chisel3.util.simpleClassName * @see [[Valid$ Valid factory]] for concrete examples * @groupdesc Signals The actual hardware fields of the Bundle */ -class Valid[+T <: Data](gen: T) extends Bundle { +class Valid[+T <: Data](gen: () => T) extends Bundle { + + @deprecated( + "Use companion object apply to make a Valid. Use constructor that takes () => T if extending Valid.", + "Chisel 7.9.0" + ) + def this(gen: T) = this(() => gen) /** A bit that will be asserted when `bits` is valid * @group Signals @@ -31,7 +37,7 @@ class Valid[+T <: Data](gen: T) extends Bundle { /** The data to be transferred, qualified by `valid` * @group Signals */ - val bits = Output(gen) + val bits = Output(gen()) /** True when `valid` is asserted * @return a Chisel [[Bool]] true if `valid` is asserted @@ -41,7 +47,7 @@ class Valid[+T <: Data](gen: T) extends Bundle { /** A non-ambiguous name of this `Valid` instance for use in generated Verilog names * Inserts the parameterized generator's typeName, e.g. Valid_UInt4 */ - override def typeName = s"${simpleClassName(this.getClass)}_${gen.typeName}" + override def typeName = s"${simpleClassName(this.getClass)}_${bits.typeName}" /** Applies the supplied functor to the bits of this interface, returning a new typed Valid interface. * @param f The function to apply to this Valid's 'bits' with return type B @@ -94,5 +100,5 @@ object Valid { * @param gen the data to wrap * @return the wrapped input data */ - def apply[T <: Data](gen: T): Valid[T] = new Valid(gen) + def apply[T <: Data](gen: T): Valid[T] = new Valid(() => gen) } diff --git a/src/test/scala-2/chiselTests/Vec.scala b/src/test/scala-2/chiselTests/Vec.scala index 3bd6f619e69..1bf587124bf 100644 --- a/src/test/scala-2/chiselTests/Vec.scala +++ b/src/test/scala-2/chiselTests/Vec.scala @@ -3,7 +3,7 @@ package chiselTests import chisel3._ -import chisel3.util.{Counter, DecoupledIO} +import chisel3.util.{Counter, Decoupled, DecoupledIO} import circt.stage.ChiselStage import org.scalatest.matchers.should.Matchers import org.scalatest.propspec.AnyPropSpec @@ -29,8 +29,8 @@ class HugeVecTester(n: Int) extends RawModule { class ReduceTreeTester extends Module { class FooIO[T <: Data](n: Int, private val gen: T) extends Bundle { - val in = Flipped(Vec(n, new DecoupledIO(gen))) - val out = new DecoupledIO(gen) + val in = Flipped(Vec(n, Decoupled(gen))) + val out = Decoupled(gen) } class Foo[T <: Data](n: Int, private val gen: T) extends Module { @@ -39,7 +39,7 @@ class ReduceTreeTester extends Module { def foo(a: DecoupledIO[T], b: DecoupledIO[T]) = { a.ready := true.B b.ready := true.B - val out = Wire(new DecoupledIO(gen)) + val out = Wire(Decoupled(gen)) out.valid := true.B diff --git a/src/test/scala-2/chiselTests/experimental/hierarchy/InstanceSpec.scala b/src/test/scala-2/chiselTests/experimental/hierarchy/InstanceSpec.scala index abcad3391b7..8037837d09b 100644 --- a/src/test/scala-2/chiselTests/experimental/hierarchy/InstanceSpec.scala +++ b/src/test/scala-2/chiselTests/experimental/hierarchy/InstanceSpec.scala @@ -7,7 +7,7 @@ import chisel3._ import chisel3.experimental.BaseModule import chisel3.experimental.hierarchy.{instantiable, public, Definition, Instance} import chisel3.testing.scalatest.FileCheck -import chisel3.util.{DecoupledIO, Valid} +import chisel3.util.{Decoupled, DecoupledIO, Valid} import chisel3.experimental.{attach, Analog} import chisel3.stage.{ChiselGeneratorAnnotation, DesignAnnotation} import circt.stage.ChiselStage @@ -1049,6 +1049,7 @@ class InstanceSpec extends AnyFunSpec with Matchers with Utils with FileCheck { ignore("(7.b): should work on Aggregate Views") { import chiselTests.experimental.FlatDecoupledDataView._ type RegDecoupled = DecoupledIO[FizzBuzz] + val RegDecoupled = Decoupled @instantiable class MyModule extends RawModule { private val a = IO(Flipped(new FlatDecoupled)) @@ -1059,8 +1060,8 @@ class InstanceSpec extends AnyFunSpec with Matchers with Utils with FileCheck { deq <> enq } class Top extends RawModule { - val foo = IO(Flipped(new RegDecoupled(new FizzBuzz))) - val bar = IO(new RegDecoupled(new FizzBuzz)) + val foo = IO(Flipped(RegDecoupled(new FizzBuzz))) + val bar = IO(RegDecoupled(new FizzBuzz)) val i = Instance(Definition(new MyModule)) i.enq <> foo i.enq_valid := foo.valid // Make sure connections also work for @public on elements of a larger Aggregate diff --git a/src/test/scala-2/chiselTests/reflect/DataMirrorSpec.scala b/src/test/scala-2/chiselTests/reflect/DataMirrorSpec.scala index a5e045bebf8..2ab1c4a503e 100644 --- a/src/test/scala-2/chiselTests/reflect/DataMirrorSpec.scala +++ b/src/test/scala-2/chiselTests/reflect/DataMirrorSpec.scala @@ -8,7 +8,7 @@ import chisel3.experimental.hierarchy._ import chisel3.probe.Probe import chisel3.properties.Property import chisel3.reflect.DataMirror -import chisel3.util.DecoupledIO +import chisel3.util.Decoupled import circt.stage.ChiselStage import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers @@ -184,9 +184,9 @@ class DataMirrorSpec extends AnyFlatSpec with Matchers { "isFullyAligned" should "work" in { class InputOutputTest extends Bundle { - val incoming = Input(DecoupledIO(UInt(8.W))) - val outgoing = Output(DecoupledIO(UInt(8.W))) - val mixed = DecoupledIO(UInt(8.W)) + val incoming = Input(Decoupled(UInt(8.W))) + val outgoing = Output(Decoupled(UInt(8.W))) + val mixed = Decoupled(UInt(8.W)) } // Top-level negative test. assert(!DataMirror.isFullyAligned(new InputOutputTest())) @@ -205,15 +205,15 @@ class DataMirrorSpec extends AnyFlatSpec with Matchers { assert(DataMirror.isFullyAligned(Input(new InputOutputTest().mixed))) // Check DecoupledIO directly, as well as coerced. - assert(!DataMirror.isFullyAligned(new DecoupledIO(UInt(8.W)))) - assert(DataMirror.isFullyAligned(Input(new DecoupledIO(UInt(8.W))))) + assert(!DataMirror.isFullyAligned(Decoupled(UInt(8.W)))) + assert(DataMirror.isFullyAligned(Input(Decoupled(UInt(8.W))))) // Positive test, simple vector + flipped vector. assert(DataMirror.isFullyAligned(Vec(2, UInt(1.W)))) assert(DataMirror.isFullyAligned(Flipped(Vec(2, UInt(1.W))))) // Positive test, zero-length vector of non-aligned elements. - assert(DataMirror.isFullyAligned(Vec(0, new DecoupledIO(UInt(8.W))))) + assert(DataMirror.isFullyAligned(Vec(0, Decoupled(UInt(8.W))))) // Negative test: vector of flipped (?). assert(!DataMirror.isFullyAligned(Vec(2, Flipped(UInt(1.W))))) diff --git a/src/test/scala/chiselTests/ReduceTreeSpec.scala b/src/test/scala/chiselTests/ReduceTreeSpec.scala index 729a28f45ce..3e5661f1fd5 100644 --- a/src/test/scala/chiselTests/ReduceTreeSpec.scala +++ b/src/test/scala/chiselTests/ReduceTreeSpec.scala @@ -5,13 +5,13 @@ package chiselTests import chisel3._ import chisel3.simulator.scalatest.ChiselSim import chisel3.simulator.stimulus.RunUntilFinished -import chisel3.util.{is, switch, DecoupledIO, Enum} +import chisel3.util.{is, switch, Decoupled, DecoupledIO, Enum} import org.scalatest.propspec.AnyPropSpec class Arbiter[T <: Data: Manifest](n: Int, private val gen: T) extends Module { val io = IO(new Bundle { - val in = Flipped(Vec(n, new DecoupledIO(gen))) - val out = new DecoupledIO(gen) + val in = Flipped(Vec(n, Decoupled(gen))) + val out = Decoupled(gen) }) def arbitrateTwo(a: DecoupledIO[T], b: DecoupledIO[T]) = { @@ -19,7 +19,7 @@ class Arbiter[T <: Data: Manifest](n: Int, private val gen: T) extends Module { val idleA :: idleB :: hasA :: hasB :: Nil = Enum(4) val regData = Reg(gen) val regState = RegInit(idleA) - val out = Wire(new DecoupledIO(gen)) + val out = Wire(Decoupled(gen)) a.ready := regState === idleA b.ready := regState === idleB