Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions src/main/scala/chisel3/util/Decoupled.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand All @@ -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
Expand Down
13 changes: 10 additions & 3 deletions src/main/scala/chisel3/util/Irrevocable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/chisel3/util/Queue.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
9 changes: 6 additions & 3 deletions src/main/scala/chisel3/util/ReadyValidIO.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand Down
14 changes: 10 additions & 4 deletions src/main/scala/chisel3/util/Valid.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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)
}
8 changes: 4 additions & 4 deletions src/test/scala-2/chiselTests/Vec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand All @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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))
Expand All @@ -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
Expand Down
14 changes: 7 additions & 7 deletions src/test/scala-2/chiselTests/reflect/DataMirrorSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()))
Expand All @@ -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)))))
Expand Down
8 changes: 4 additions & 4 deletions src/test/scala/chiselTests/ReduceTreeSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@ 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]) = {

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
Expand Down