From a66d2d152897fa979aea07aa067c27ba455ca054 Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Wed, 12 Aug 2020 22:17:21 -0700 Subject: Deprecate Module.io and BlackBox.io (#1550) * Deprecate Module.io and BlackBox.io This is a step toward unification of Module with MultiIOModule. The future of BlackBox is a bit less clear, but its existing API can be maintained without the io virtual method. The trickier API to maintain is auto-IO wrapping for compatibility Modules and BlackBoxes. This will probably require reflection to support once the io virtual method is removed. * Improve deprecation warning for io--- core/src/main/scala/chisel3/BlackBox.scala | 23 ++++++++++++++++------- core/src/main/scala/chisel3/RawModule.scala | 16 ++++++++++++---- 2 files changed, 28 insertions(+), 11 deletions(-) (limited to 'core/src') diff --git a/core/src/main/scala/chisel3/BlackBox.scala b/core/src/main/scala/chisel3/BlackBox.scala index 8c5138d5..8493196b 100644 --- a/core/src/main/scala/chisel3/BlackBox.scala +++ b/core/src/main/scala/chisel3/BlackBox.scala @@ -133,23 +133,32 @@ package experimental { * @note The parameters API is experimental and may change */ abstract class BlackBox(val params: Map[String, Param] = Map.empty[String, Param])(implicit compileOptions: CompileOptions) extends BaseBlackBox { + + @deprecated("Removed for causing issues in Scala 2.12+. You remain free to define io Bundles " + + "in your BlackBoxes, but you cannot rely on an io field in every BlackBox. " + + "For more information, see: https://github.com/freechipsproject/chisel3/pull/1550.", + "Chisel 3.4" + ) def io: Record + // Private accessor to reduce number of deprecation warnings + private[chisel3] def _io: Record = io + // Allow access to bindings from the compatibility package - protected def _compatIoPortBound() = portsContains(io) + protected def _compatIoPortBound() = portsContains(_io) private[chisel3] override def generateComponent(): Component = { _compatAutoWrapPorts() // pre-IO(...) compatibility hack // Restrict IO to just io, clock, and reset - require(io != null, "BlackBox must have io") - require(portsContains(io), "BlackBox must have io wrapped in IO(...)") + require(_io != null, "BlackBox must have io") + require(portsContains(_io), "BlackBox must have io wrapped in IO(...)") require(portsSize == 1, "BlackBox must only have io as IO") require(!_closed, "Can't generate module more than once") _closed = true - val namedPorts = io.elements.toSeq.reverse // ListMaps are stored in reverse order + val namedPorts = _io.elements.toSeq.reverse // ListMaps are stored in reverse order // setRef is not called on the actual io. // There is a risk of user improperly attempting to connect directly with io @@ -163,18 +172,18 @@ abstract class BlackBox(val params: Map[String, Param] = Map.empty[String, Param // of the io bundle, but NOT on the io bundle itself. // Doing so would cause the wrong names to be assigned, since their parent // is now the module itself instead of the io bundle. - for (id <- getIds; if id ne io) { + for (id <- getIds; if id ne _io) { id._onModuleClose } val firrtlPorts = namedPorts map {namedPort => Port(namedPort._2, namedPort._2.specifiedDirection)} - val component = DefBlackBox(this, name, firrtlPorts, io.specifiedDirection, params) + val component = DefBlackBox(this, name, firrtlPorts, _io.specifiedDirection, params) _component = Some(component) component } private[chisel3] def initializeInParent(parentCompileOptions: CompileOptions): Unit = { - for ((_, port) <- io.elements) { + for ((_, port) <- _io.elements) { pushCommand(DefInvalid(UnlocatableSourceInfo, port.ref)) } } diff --git a/core/src/main/scala/chisel3/RawModule.scala b/core/src/main/scala/chisel3/RawModule.scala index a1006594..16a2394f 100644 --- a/core/src/main/scala/chisel3/RawModule.scala +++ b/core/src/main/scala/chisel3/RawModule.scala @@ -200,10 +200,18 @@ package internal { // IO for this Module. At the Scala level (pre-FIRRTL transformations), // connections in and out of a Module may only go through `io` elements. + @deprecated("Removed for causing issues in Scala 2.12+. You remain free to define io Bundles " + + "in your Modules, but you cannot rely on an io field in every Module. " + + "For more information, see: https://github.com/freechipsproject/chisel3/pull/1550.", + "Chisel 3.4" + ) def io: Record + // Private accessor to reduce number of deprecation warnings + private[chisel3] def _io: Record = io + // Allow access to bindings from the compatibility package - protected def _compatIoPortBound() = portsContains(io) + protected def _compatIoPortBound() = portsContains(_io) private[chisel3] override def namePorts(names: HashMap[HasId, String]): Unit = { for (port <- getModulePorts) { @@ -218,8 +226,8 @@ package internal { _compatAutoWrapPorts() // pre-IO(...) compatibility hack // Restrict IO to just io, clock, and reset - require(io != null, "Module must have io") - require(portsContains(io), "Module must have io wrapped in IO(...)") + require(_io != null, "Module must have io") + require(portsContains(_io), "Module must have io wrapped in IO(...)") require((portsContains(clock)) && (portsContains(reset)), "Internal error, module did not have clock or reset as IO") require(portsSize == 3, "Module must only have io, clock, and reset as IO") @@ -232,7 +240,7 @@ package internal { implicit val sourceInfo = UnlocatableSourceInfo if (!parentCompileOptions.explicitInvalidate) { - pushCommand(DefInvalid(sourceInfo, io.ref)) + pushCommand(DefInvalid(sourceInfo, _io.ref)) } clock := override_clock.getOrElse(Builder.forcedClock) -- cgit v1.2.3