diff --git a/core/src/main/scala-2/chisel3/LogicalEachIntf.scala b/core/src/main/scala-2/chisel3/LogicalEachIntf.scala new file mode 100644 index 00000000000..3f9b8a71b4f --- /dev/null +++ b/core/src/main/scala-2/chisel3/LogicalEachIntf.scala @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: Apache-2.0 + +package chisel3 + +import scala.language.experimental.macros + +import chisel3.experimental.SourceInfo +import chisel3.internal.sourceinfo.LogicalEachTransform + +private[chisel3] trait LogicalEachIntf extends SourceInfoDoc { self: LogicalEach => + + /** Wide logical operator. Every bit of data is combined with the Boolean operand. + * + * @param cond Bool operand to be applied to each bit of the input data + * @param data the data to be qualified by the control signal + * @example + * {{{ + * val dataQualified = AndEach(enable, value) + * }}} + */ + def apply[T <: Data](cond: Bool, data: T): T = macro LogicalEachTransform.apply[T] + + /** @group SourceInfoTransformMacro */ + def do_apply[T <: Data]( + cond: Bool, + data: T + )( + implicit sourceInfo: SourceInfo + ): T = _applyImpl(cond, data) +} diff --git a/core/src/main/scala-3/chisel3/LogicalEachIntf.scala b/core/src/main/scala-3/chisel3/LogicalEachIntf.scala new file mode 100644 index 00000000000..9af2bd9811c --- /dev/null +++ b/core/src/main/scala-3/chisel3/LogicalEachIntf.scala @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: Apache-2.0 + +package chisel3 + +import chisel3.experimental.SourceInfo + +private[chisel3] trait LogicalEachIntf extends SourceInfoDoc { self: LogicalEach => + + /** Wide logical operator. Every bit of data is combined with the Boolean operand. + * + * @param cond Bool operand to be applied to each bit of the input data + * @param data the data to be qualified by the control signal + * @example + * {{{ + * val dataQualified = AndEach(enable, value) + * }}} + */ + + def apply[T <: Data]( + cond: Bool, + data: T + )( + using SourceInfo + ): T = _applyImpl(cond, data) +} diff --git a/core/src/main/scala/chisel3/LogicalEach.scala b/core/src/main/scala/chisel3/LogicalEach.scala new file mode 100644 index 00000000000..6f0eb516034 --- /dev/null +++ b/core/src/main/scala/chisel3/LogicalEach.scala @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: Apache-2.0 + +package chisel3 + +import scala.language.experimental.macros + +import chisel3.experimental.SourceInfo + +private[chisel3] trait LogicalEach { + protected def _applyImpl[T <: Data]( + cond: Bool, + data: T + )( + implicit sourceInfo: SourceInfo + ): T +} + +object AndEach extends LogicalEach with LogicalEachIntf { + protected def _applyImpl[T <: Data]( + cond: Bool, + data: T + )( + implicit sourceInfo: SourceInfo + ): T = { + Mux(cond, data, (0.U).asTypeOf(data)) + } +} + +// Can implement OrEach / XorEach later, if there is a use case diff --git a/macros/src/main/scala-2/chisel3/internal/sourceinfo/SourceInfoTransform.scala b/macros/src/main/scala-2/chisel3/internal/sourceinfo/SourceInfoTransform.scala index d366e22fd22..b57fc62e7ad 100644 --- a/macros/src/main/scala-2/chisel3/internal/sourceinfo/SourceInfoTransform.scala +++ b/macros/src/main/scala-2/chisel3/internal/sourceinfo/SourceInfoTransform.scala @@ -102,6 +102,15 @@ class MuxTransform(val c: Context) extends SourceInfoTransformMacro { } } +object LogicalEachTransform +class LogicalEachTransform(val c: Context) extends SourceInfoTransformMacro { + import c.universe._ + def apply[T: c.WeakTypeTag](cond: c.Tree, data: c.Tree): c.Tree = { + val tpe = weakTypeOf[T] + q"$thisObj.do_apply[$tpe]($cond, $data)($implicitSourceInfo)" + } +} + class MuxLookupTransform(val c: Context) extends SourceInfoTransformMacro { import c.universe._ diff --git a/src/test/scala/chiselTests/MuxSpec.scala b/src/test/scala/chiselTests/MuxSpec.scala index e66ff71f894..80fa0b56abc 100644 --- a/src/test/scala/chiselTests/MuxSpec.scala +++ b/src/test/scala/chiselTests/MuxSpec.scala @@ -22,6 +22,21 @@ class MuxTester extends Module { dontCareMux2 := Mux(1.B, 3.U, DontCare) // note: Mux output of type Element assert(dontCareMux2 === 3.U) + assert(AndEach(false.B, 51.U) === 0.U) + assert(AndEach(true.B, 51.U) === 51.U) + val myBundle = new Bundle { + val a = UInt(4.W) + val b = Vec(2, UInt(4.W)) + } + val b = Wire(myBundle) + b.a := 9.U + b.b(0) := 3.U + b.b(1) := 5.U + val bQualified = AndEach(true.B, b) + val bDisqualified = AndEach(false.B, b) + assert(bQualified === b) + assert(bDisqualified === 0.U.asTypeOf(b)) + Mux(0.B, 3.U, DontCare) // just to make sure nothing crashes, any result is valid stop() }