diff options
40 files changed, 328 insertions, 260 deletions
@@ -18,10 +18,6 @@ lazy val commonSettings = Seq ( scalaVersion := "2.12.12", crossScalaVersions := Seq("2.12.12"), scalacOptions := Seq("-deprecation", "-feature", - // We're building with Scala > 2.11, enable the compile option - // switch to support our anonymous Bundle definitions: - // https://github.com/scala/bug/issues/10047 - "-Xsource:2.11" ), libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value, addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full), @@ -59,8 +59,7 @@ trait CommonModule extends CrossSbtModule with PublishModule { override def scalacOptions = T { super.scalacOptions() ++ Agg( "-deprecation", - "-feature", - "-Xsource:2.11" + "-feature" ) } diff --git a/core/src/main/scala/chisel3/Annotation.scala b/core/src/main/scala/chisel3/Annotation.scala index c8ac462d..545ea480 100644 --- a/core/src/main/scala/chisel3/Annotation.scala +++ b/core/src/main/scala/chisel3/Annotation.scala @@ -4,7 +4,7 @@ package chisel3.experimental import scala.language.existentials import chisel3.internal.{Builder, InstanceId, LegacyModule} -import chisel3.{CompileOptions, Data} +import chisel3.{CompileOptions, Data, RawModule} import firrtl.Transform import firrtl.annotations._ import firrtl.options.Unserializable @@ -78,7 +78,7 @@ object doNotDedup { * @param module The module to be marked * @return Unmodified signal `module` */ - def apply[T <: LegacyModule](module: T)(implicit compileOptions: CompileOptions): Unit = { + def apply[T <: RawModule](module: T)(implicit compileOptions: CompileOptions): Unit = { annotate(new ChiselAnnotation { def toFirrtl = NoDedupAnnotation(module.toNamed) }) } } diff --git a/core/src/main/scala/chisel3/BlackBox.scala b/core/src/main/scala/chisel3/BlackBox.scala index 1b093ee1..03543790 100644 --- a/core/src/main/scala/chisel3/BlackBox.scala +++ b/core/src/main/scala/chisel3/BlackBox.scala @@ -134,15 +134,11 @@ package experimental { */ 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 + // Find a Record port named "io" for purposes of stripping the prefix + private[chisel3] lazy val _io: Record = + this.findPort("io") + .collect { case r: Record => r } // Must be a Record + .getOrElse(null) // null handling occurs in generateComponent // Allow access to bindings from the compatibility package protected def _compatIoPortBound() = portsContains(_io) @@ -151,9 +147,9 @@ abstract class BlackBox(val params: Map[String, Param] = Map.empty[String, Param _compatAutoWrapPorts() // pre-IO(...) compatibility hack // Restrict IO to just io, clock, and reset - require(_io != null, "BlackBox must have io") + require(_io != null, "BlackBox must have a port named 'io' of type Record!") require(portsContains(_io), "BlackBox must have io wrapped in IO(...)") - require(portsSize == 1, "BlackBox must only have io as IO") + require(portsSize == 1, "BlackBox must only have one IO, called `io`") require(!_closed, "Can't generate module more than once") _closed = true diff --git a/core/src/main/scala/chisel3/Module.scala b/core/src/main/scala/chisel3/Module.scala index 236f528e..d34211f1 100644 --- a/core/src/main/scala/chisel3/Module.scala +++ b/core/src/main/scala/chisel3/Module.scala @@ -6,15 +6,14 @@ import scala.collection.immutable.ListMap import scala.collection.mutable.{ArrayBuffer, HashMap} import scala.collection.JavaConversions._ import scala.language.experimental.macros - import java.util.IdentityHashMap import chisel3.internal._ import chisel3.internal.Builder._ import chisel3.internal.firrtl._ -import chisel3.internal.sourceinfo.{InstTransform, SourceInfo} +import chisel3.internal.sourceinfo.{InstTransform, SourceInfo, UnlocatableSourceInfo} import chisel3.experimental.BaseModule -import _root_.firrtl.annotations.{ModuleName, ModuleTarget, IsModule} +import _root_.firrtl.annotations.{IsModule, ModuleName, ModuleTarget} object Module extends SourceInfoDoc { /** A wrapper method that all Module instantiations must be wrapped in @@ -87,6 +86,56 @@ object Module extends SourceInfoDoc { def currentModule: Option[BaseModule] = Builder.currentModule } +/** Abstract base class for Modules, which behave much like Verilog modules. + * These may contain both logic and state which are written in the Module + * body (constructor). + * This abstract base class includes an implicit clock and reset. + * + * @note Module instantiations must be wrapped in a Module() call. + */ +abstract class Module(implicit moduleCompileOptions: CompileOptions) extends RawModule { + // Implicit clock and reset pins + final val clock: Clock = IO(Input(Clock())).suggestName("clock") + final val reset: Reset = IO(Input(mkReset)).suggestName("reset") + + // TODO It's hard to remove these deprecated override methods because they're used by + // Chisel.QueueCompatibility which extends chisel3.Queue which extends chisel3.Module + private var _override_clock: Option[Clock] = None + private var _override_reset: Option[Bool] = None + @deprecated("Use withClock at Module instantiation", "Chisel 3.5") + protected def override_clock: Option[Clock] = _override_clock + @deprecated("Use withClock at Module instantiation", "Chisel 3.5") + protected def override_reset: Option[Bool] = _override_reset + @deprecated("Use withClock at Module instantiation", "Chisel 3.5") + protected def override_clock_=(rhs: Option[Clock]): Unit = { + _override_clock = rhs + } + @deprecated("Use withClock at Module instantiation", "Chisel 3.5") + protected def override_reset_=(rhs: Option[Bool]): Unit = { + _override_reset = rhs + } + + private[chisel3] def mkReset: Reset = { + // Top module and compatibility mode use Bool for reset + val inferReset = _parent.isDefined && moduleCompileOptions.inferModuleReset + if (inferReset) Reset() else Bool() + } + + // Setup ClockAndReset + Builder.currentClock = Some(clock) + Builder.currentReset = Some(reset) + Builder.clearPrefix() + + private[chisel3] override def initializeInParent(parentCompileOptions: CompileOptions): Unit = { + implicit val sourceInfo = UnlocatableSourceInfo + + super.initializeInParent(parentCompileOptions) + clock := _override_clock.getOrElse(Builder.forcedClock) + reset := _override_reset.getOrElse(Builder.forcedReset) + } +} + + package experimental { object IO { @@ -145,7 +194,7 @@ package internal { if (!compileOptions.explicitInvalidate) { pushCommand(DefInvalid(sourceInfo, clonePorts.ref)) } - if (proto.isInstanceOf[MultiIOModule]) { + if (proto.isInstanceOf[Module]) { clonePorts("clock") := Module.clock clonePorts("reset") := Module.reset } @@ -208,6 +257,11 @@ package experimental { // mainly for compatibility purposes. protected def portsContains(elem: Data): Boolean = _ports contains elem + // This is dangerous because it can be called before the module is closed and thus there could + // be more ports and names have not yet been finalized. + // This should only to be used during the process of closing when it is safe to do so. + private[chisel3] def findPort(name: String): Option[Data] = _ports.find(_.seedOpt.contains(name)) + protected def portsSize: Int = _ports.size /** Generates the FIRRTL Component (Module or Blackbox) of this Module. diff --git a/core/src/main/scala/chisel3/RawModule.scala b/core/src/main/scala/chisel3/RawModule.scala index 9f0a24d6..0adacedb 100644 --- a/core/src/main/scala/chisel3/RawModule.scala +++ b/core/src/main/scala/chisel3/RawModule.scala @@ -3,6 +3,7 @@ package chisel3 import scala.collection.mutable.{ArrayBuffer, HashMap} +import scala.util.Try import scala.collection.JavaConversions._ import scala.language.experimental.macros @@ -142,86 +143,83 @@ abstract class RawModule(implicit moduleCompileOptions: CompileOptions) } } -trait RequireAsyncReset extends MultiIOModule { +trait RequireAsyncReset extends Module { override private[chisel3] def mkReset: AsyncReset = AsyncReset() } -trait RequireSyncReset extends MultiIOModule { +trait RequireSyncReset extends Module { override private[chisel3] def mkReset: Bool = Bool() } -/** Abstract base class for Modules, which behave much like Verilog modules. - * These may contain both logic and state which are written in the Module - * body (constructor). - * This abstract base class includes an implicit clock and reset. - * - * @note Module instantiations must be wrapped in a Module() call. - */ -abstract class MultiIOModule(implicit moduleCompileOptions: CompileOptions) - extends RawModule { - // Implicit clock and reset pins - final val clock: Clock = IO(Input(Clock())).autoSeed("clock") - final val reset: Reset = IO(Input(mkReset)).autoSeed("reset") - - private[chisel3] def mkReset: Reset = { - // Top module and compatibility mode use Bool for reset - val inferReset = _parent.isDefined && moduleCompileOptions.inferModuleReset - if (inferReset) Reset() else Bool() - } - - // Setup ClockAndReset - Builder.currentClock = Some(clock) - Builder.currentReset = Some(reset) - Builder.clearPrefix() - - private[chisel3] override def initializeInParent(parentCompileOptions: CompileOptions): Unit = { - implicit val sourceInfo = UnlocatableSourceInfo +package object internal { + + // Private reflective version of "val io" to maintain Chisel.Module semantics without having + // io as a virtual method. See https://github.com/freechipsproject/chisel3/pull/1550 for more + // information about the removal of "val io" + private def reflectivelyFindValIO(self: BaseModule): Record = { + // Java reflection is faster and works for the common case + def tryJavaReflect: Option[Record] = Try { + self.getClass.getMethod("io").invoke(self).asInstanceOf[Record] + }.toOption + // Anonymous subclasses don't work with Java reflection, so try slower, Scala reflection + def tryScalaReflect: Option[Record] = { + val ru = scala.reflect.runtime.universe + import ru.{Try => _, _} + val m = ru.runtimeMirror(self.getClass.getClassLoader) + val im = m.reflect(self) + val tpe = im.symbol.toType + // For some reason, in anonymous subclasses, looking up the Term by name (TermName("io")) + // hits an internal exception. Searching for the term seems to work though so we use that. + val ioTerm: Option[TermSymbol] = tpe.decls.collectFirst { + case d if d.name.toString == "io" && d.isTerm => d.asTerm + } + ioTerm.flatMap { term => + Try { + im.reflectField(term).get.asInstanceOf[Record] + }.toOption + } + } - super.initializeInParent(parentCompileOptions) - clock := Builder.forcedClock - reset := Builder.forcedReset + tryJavaReflect + .orElse(tryScalaReflect) + .map(_.autoSeed("io")) + .orElse { + // Fallback if reflection fails, user can wrap in IO(...) + self.findPort("io") + .collect { case r: Record => r } + }.getOrElse(throwException( + s"Compatibility mode Module '$this' must have a 'val io' Bundle. " + + "If there is such a field and you still see this error, autowrapping has failed (sorry!). " + + "Please wrap the Bundle declaration in IO(...)." + )) } -} - -package internal { /** Legacy Module class that restricts IOs to just io, clock, and reset, and provides a constructor * for threading through explicit clock and reset. * - * While this class isn't planned to be removed anytime soon (there are benefits to restricting - * IO), the clock and reset constructors will be phased out. Recommendation is to wrap the module - * in a withClock/withReset/withClockAndReset block, or directly hook up clock or reset IO pins. + * '''Do not use this class in user code'''. Use whichever `Module` is imported by your wildcard + * import (preferably `import chisel3._`). */ - abstract class LegacyModule(implicit moduleCompileOptions: CompileOptions) - extends MultiIOModule { - // These are to be phased out - protected var override_clock: Option[Clock] = None - protected var override_reset: Option[Bool] = None - - // 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 + abstract class LegacyModule(implicit moduleCompileOptions: CompileOptions) extends Module { + // Provide a non-deprecated constructor + def this(override_clock: Option[Clock] = None, override_reset: Option[Bool]=None) + (implicit moduleCompileOptions: CompileOptions) = { + this() + this.override_clock = override_clock + this.override_reset = override_reset + } + def this(_clock: Clock)(implicit moduleCompileOptions: CompileOptions) = + this(Option(_clock), None)(moduleCompileOptions) + def this(_reset: Bool)(implicit moduleCompileOptions: CompileOptions) = + this(None, Option(_reset))(moduleCompileOptions) + def this(_clock: Clock, _reset: Bool)(implicit moduleCompileOptions: CompileOptions) = + this(Option(_clock), Option(_reset))(moduleCompileOptions) + + private lazy val _io: Record = reflectivelyFindValIO(this) // Allow access to bindings from the compatibility package protected def _compatIoPortBound() = portsContains(_io) - private[chisel3] override def namePorts(names: HashMap[HasId, String]): Unit = { - for (port <- getModulePorts) { - // This should already have been caught - if (!names.contains(port)) throwException(s"Unable to name port $port in $this") - val name = names(port) - port.setRef(ModuleIO(this, _namespace.name(name))) - } - } - private[chisel3] override def generateComponent(): Component = { _compatAutoWrapPorts() // pre-IO(...) compatibility hack @@ -234,17 +232,32 @@ package internal { super.generateComponent() } - private[chisel3] override def initializeInParent(parentCompileOptions: CompileOptions): Unit = { - // Don't generate source info referencing parents inside a module, since this interferes with - // module de-duplication in FIRRTL emission. - implicit val sourceInfo = UnlocatableSourceInfo - - if (!parentCompileOptions.explicitInvalidate) { - pushCommand(DefInvalid(sourceInfo, _io.ref)) + override def _compatAutoWrapPorts(): Unit = { + if (!_compatIoPortBound() && _io != null) { + _bindIoInPlace(_io) } + } + } - clock := override_clock.getOrElse(Builder.forcedClock) - reset := override_reset.getOrElse(Builder.forcedReset) + import chisel3.experimental.Param + + /** Legacy BlackBox class will reflectively autowrap val io + * + * '''Do not use this class in user code'''. Use whichever `BlackBox` is imported by your wildcard + * import (preferably `import chisel3._`). + */ + abstract class LegacyBlackBox(params: Map[String, Param] = Map.empty[String, Param]) + (implicit moduleCompileOptions: CompileOptions) + extends chisel3.BlackBox(params) { + + override private[chisel3] lazy val _io: Record = reflectivelyFindValIO(this) + + // This class auto-wraps the BlackBox with IO(...), allowing legacy code (where IO(...) wasn't + // required) to build. + override def _compatAutoWrapPorts(): Unit = { + if (!_compatIoPortBound()) { + _bindIoInPlace(_io) + } } } } diff --git a/core/src/main/scala/chisel3/core/package.scala b/core/src/main/scala/chisel3/core/package.scala index 1da4ba97..fa29f244 100644 --- a/core/src/main/scala/chisel3/core/package.scala +++ b/core/src/main/scala/chisel3/core/package.scala @@ -66,13 +66,13 @@ package object core { type RawModule = chisel3.RawModule @deprecated("Avoid importing from chisel3.core, these are not public APIs and may change at any time. " + "Use chisel3.MultiIOModule instead. This alias will be removed in 3.4.", "since the beginning of time") - type MultiIOModule = chisel3.MultiIOModule + type MultiIOModule = chisel3.Module @deprecated("Avoid importing from chisel3.core, these are not public APIs and may change at any time. " + " Use chisel3.RawModule instead. This alias will be removed in 3.4.", "since the beginning of time") type UserModule = chisel3.RawModule @deprecated("Avoid importing from chisel3.core, these are not public APIs and may change at any time. " + "Use chisel3.MultiIOModule instead. This alias will be removed in 3.4.", "since the beginning of time") - type ImplicitModule = chisel3.MultiIOModule + type ImplicitModule = chisel3.Module @deprecated("Use the version in chisel3._", "3.2") val Bits = chisel3.Bits diff --git a/core/src/main/scala/chisel3/package.scala b/core/src/main/scala/chisel3/package.scala index fb83c9d9..d5a4bfae 100644 --- a/core/src/main/scala/chisel3/package.scala +++ b/core/src/main/scala/chisel3/package.scala @@ -167,7 +167,8 @@ package object chisel3 { type InstanceId = internal.InstanceId - type Module = chisel3.internal.LegacyModule + @deprecated("MultiIOModule is now just Module", "Chisel 3.5") + type MultiIOModule = chisel3.Module /** Implicit for custom Printable string interpolator */ implicit class PrintableHelper(val sc: StringContext) extends AnyVal { diff --git a/docs/src/cookbooks/naming.md b/docs/src/cookbooks/naming.md index 098ea898..a41a1e9a 100644 --- a/docs/src/cookbooks/naming.md +++ b/docs/src/cookbooks/naming.md @@ -48,7 +48,7 @@ Use the `.suggestName` method, which is on all classes which subtype `Data`. You can use the `noPrefix { ... }` to strip the prefix from all signals generated in that scope. ```scala mdoc -class ExampleNoPrefix extends MultiIOModule { +class ExampleNoPrefix extends Module { val in = IO(Input(UInt(2.W))) val out = IO(Output(UInt())) @@ -68,14 +68,14 @@ In cases where a FIRRTL transform renames a signal/instance, you can use the `fo ```scala mdoc import chisel3.util.experimental.{forceName, InlineInstance} -class WrapperExample extends MultiIOModule { +class WrapperExample extends Module { val in = IO(Input(UInt(3.W))) val out = IO(Output(UInt(3.W))) val inst = Module(new Wrapper) inst.in := in out := inst.out } -class Wrapper extends MultiIOModule with InlineInstance { +class Wrapper extends Module with InlineInstance { val in = IO(Input(UInt(3.W))) val out = IO(Output(UInt(3.W))) val inst = Module(new MyLeaf) @@ -83,7 +83,7 @@ class Wrapper extends MultiIOModule with InlineInstance { inst.in := in out := inst.out } -class MyLeaf extends MultiIOModule { +class MyLeaf extends Module { val in = IO(Input(UInt(3.W))) val out = IO(Output(UInt(3.W))) out := in diff --git a/docs/src/explanations/naming.md b/docs/src/explanations/naming.md index fb1121f9..60c653aa 100644 --- a/docs/src/explanations/naming.md +++ b/docs/src/explanations/naming.md @@ -44,7 +44,7 @@ class MyBundle extends Bundle { val foo = Input(UInt(3.W)) // val foo = autoNameRecursively("foo")(Input(UInt(3.W))) } -class Example1 extends MultiIOModule { +class Example1 extends Module { val io = IO(new MyBundle()) // val io = autoNameRecursively("io")(IO(new MyBundle())) } @@ -57,7 +57,7 @@ Otherwise, it is rewritten to also include the name as a prefix to any signals g side of the val declaration: ```scala mdoc -class Example2 extends MultiIOModule { +class Example2 extends Module { val in = IO(Input(UInt(2.W))) // val in = autoNameRecursively("in")(prefix("in")(IO(Input(UInt(2.W))))) @@ -80,7 +80,7 @@ ChiselStage.emitVerilog(new Example2) Note that the naming also works if the hardware type is nested in an `Option` or a subtype of `Iterable`: ```scala mdoc -class Example3 extends MultiIOModule { +class Example3 extends Module { val in = IO(Input(UInt(2.W))) // val in = autoNameRecursively("in")(prefix("in")(IO(Input(UInt(2.W))))) @@ -102,7 +102,7 @@ ChiselStage.emitVerilog(new Example3) There is also a slight variant (`autoNameRecursivelyProduct`) for naming hardware with names provided by an unapply: ```scala mdoc -class UnapplyExample extends MultiIOModule { +class UnapplyExample extends Module { def mkIO() = (IO(Input(UInt(2.W))), IO(Output(UInt()))) val (in, out) = mkIO() // val (in, out) = autoNameRecursivelyProduct(List(Some("in"), Some("out")))(mkIO()) @@ -126,7 +126,7 @@ but don't want to influence other names in the module. In the following example, we prefix additional logic with "ECO", where `Example4` is pre-ECO and `Example5` is post-ECO: ```scala mdoc -class Example4 extends MultiIOModule { +class Example4 extends Module { val in = IO(Input(UInt(2.W))) val out = IO(Output(UInt())) @@ -135,7 +135,7 @@ class Example4 extends MultiIOModule { out := add + 1.U } -class Example5 extends MultiIOModule { +class Example5 extends Module { val in = IO(Input(UInt(2.W))) val out = IO(Output(UInt())) @@ -152,7 +152,7 @@ ChiselStage.emitVerilog(new Example5) Also note that the prefixes append to each other (including the prefix generated by the compiler plugin): ```scala mdoc -class Example6 extends MultiIOModule { +class Example6 extends Module { val in = IO(Input(UInt(2.W))) val out = IO(Output(UInt())) @@ -169,7 +169,7 @@ Sometimes you may want to disable the prefixing. This might occur if you are wri don't want the prefixing behavior. In this case, you can use the `noPrefix` object: ```scala mdoc -class Example7 extends MultiIOModule { +class Example7 extends Module { val in = IO(Input(UInt(2.W))) val out = IO(Output(UInt())) @@ -188,7 +188,7 @@ If you want to specify the name of a signal, you can always use the `.suggestNam name will still be prefixed (including by the plugin). You can always use the `noPrefix` object to strip this. ```scala mdoc -class Example8 extends MultiIOModule { +class Example8 extends Module { val in = IO(Input(UInt(2.W))) val out = IO(Output(UInt())) @@ -208,7 +208,7 @@ value. Note that you can parameterize the name by the module's parameters. This names more stable and is highly recommended to do. ```scala mdoc -class Example9(width: Int) extends MultiIOModule { +class Example9(width: Int) extends Module { override val desiredName = s"EXAMPLE9WITHWIDTH$width" val in = IO(Input(UInt(width.W))) val out = IO(Output(UInt())) @@ -236,7 +236,7 @@ For example, the signals in the following module are in a nested scope; the plug reflection naming cannot: ```scala mdoc -class Example10 extends MultiIOModule { +class Example10 extends Module { { val in = IO(Input(UInt(3.W))) val out = IO(Output(UInt())) diff --git a/docs/src/wiki-deprecated/cookbook.md b/docs/src/wiki-deprecated/cookbook.md index 7fa97579..9a10a689 100644 --- a/docs/src/wiki-deprecated/cookbook.md +++ b/docs/src/wiki-deprecated/cookbook.md @@ -282,12 +282,12 @@ class ModuleWithOptionalIOs(flag: Boolean) extends Module { } ``` -The following is an example for a `MultiIOModule` where an entire `IO` is optional: +The following is an example where an entire `IO` is optional: ```scala mdoc:silent:reset import chisel3._ -class ModuleWithOptionalIO(flag: Boolean) extends MultiIOModule { +class ModuleWithOptionalIO(flag: Boolean) extends Module { val in = if (flag) Some(IO(Input(Bool()))) else None val out = IO(Output(Bool())) diff --git a/docs/src/wiki-deprecated/modules.md b/docs/src/wiki-deprecated/modules.md index 1d85b88e..23006c9c 100644 --- a/docs/src/wiki-deprecated/modules.md +++ b/docs/src/wiki-deprecated/modules.md @@ -10,8 +10,8 @@ The hierarchical module namespace is accessible in downstream tools to aid in debugging and physical layout. A user-defined module is defined as a *class* which: - - inherits from ```Module```, - - contains an interface wrapped in a Module's ```IO()``` method and stored in a port field named ```io```, and + - inherits from `Module`, + - contains at least one interface wrapped in a Module's `IO()` method (traditionally stored in a port field named ```io```), and - wires together subcircuits in its constructor. As an example, consider defining your own two-input multiplexer as a @@ -86,24 +86,18 @@ new object. We then wire them up to one another and to the ports of the ```Mux4``` interface. Note: Chisel `Module`s have an implicit clock (called `clock`) and -an implicit reset (called `reset`). For different behavior, Chisel -provides both `MultiIOModule` and `RawModule`. +an implicit reset (called `reset`). To create modules without implicit +clock and reset, Chisel provides `RawModule`. -### `MultiIOModule` - -A `MultiIOModule` allows you to define as many different `IO` as needed -and does not require you to implement an abstract member `io`. -This can be useful when programmatically adding `IO` or adding `IO` via inheritance. -An artifact of this is that Verilog generated from a `MultiIOModule` will -*not* have the `io_` prefix. `MultiIOModule`s still have an implicit -clock and reset like `Module`. - -<!-- TODO: Some example --> +> Historical Note: Prior to Chisel 3.5, Modules were restricted to only +having a single user-defined port named `io`. There was also a type called +`MultiIOModule` that provided implicit clock and reset while allowing the +user to define as many ports as they want. This is now the functionality +of `Module`. ### `RawModule` -A `RawModule` is a module that allows you to define as much `IO` as needed -(like `MultiIOModule`) but **does not provide an implicit clock and reset.** +A `RawModule` is a module that **does not provide an implicit clock and reset.** This can be useful when interfacing a Chisel module with a design that expects a specific naming convention for clock or reset. diff --git a/docs/src/wiki-deprecated/ports.md b/docs/src/wiki-deprecated/ports.md index f8c30b7a..251ce243 100644 --- a/docs/src/wiki-deprecated/ports.md +++ b/docs/src/wiki-deprecated/ports.md @@ -30,21 +30,20 @@ provide powerful wiring constructs described later. (Chisel 3.2+) -Chisel 3.2+ introduces an API `DataMirror.modulePorts` which can be used to inspect the IOs of any Chisel module, including MultiIOModules, RawModules, and BlackBoxes. - +Chisel 3.2 introduced `DataMirror.modulePorts` which can be used to inspect the IOs of any Chisel module (this includes modules in both `import chisel3._` and `import Chisel._`, as well as BlackBoxes from each package). Here is an example of how to use this API: ```scala import chisel3.experimental.DataMirror -class Adder extends MultiIOModule { +class Adder extends Module { val a = IO(Input(UInt(8.W))) val b = IO(Input(UInt(8.W))) val c = IO(Output(UInt(8.W))) c := a +& b } -class Test extends MultiIOModule { +class Test extends Module { val adder = Module(new Adder) // for debug only adder.a := DontCare diff --git a/docs/src/wiki-deprecated/reset.md b/docs/src/wiki-deprecated/reset.md index 3aafeccd..f5e4a24a 100644 --- a/docs/src/wiki-deprecated/reset.md +++ b/docs/src/wiki-deprecated/reset.md @@ -7,7 +7,7 @@ section: "chisel3" ```scala mdoc:invisible import chisel3._ -class Submodule extends MultiIOModule +class Submodule extends Module ``` As of Chisel 3.2.0, Chisel 3 supports both synchronous and asynchronous reset, @@ -60,13 +60,13 @@ rather than relying on _Reset Inference_, you can mixin one of the following tra For example: ```scala mdoc:silent -class MyAlwaysSyncResetModule extends MultiIOModule with RequireSyncReset { +class MyAlwaysSyncResetModule extends Module with RequireSyncReset { val mySyncResetReg = RegInit(false.B) // reset is of type Bool } ``` ```scala mdoc:silent -class MyAlwaysAsyncResetModule extends MultiIOModule with RequireAsyncReset { +class MyAlwaysAsyncResetModule extends Module with RequireAsyncReset { val myAsyncResetReg = RegInit(false.B) // reset is of type AsyncReset } ``` @@ -123,7 +123,7 @@ See ["Multiple Clock Domains"](../explanations/multi-clock) for more information The following will make `myReg` as well as both `resetAgnosticReg`s synchronously reset: ```scala mdoc:silent -class ForcedSyncReset extends MultiIOModule { +class ForcedSyncReset extends Module { // withReset's argument becomes the implicit reset in its scope withReset (reset.asBool) { val myReg = RegInit(0.U) @@ -140,7 +140,7 @@ class ForcedSyncReset extends MultiIOModule { The following will make `myReg` as well as both `resetAgnosticReg`s asynchronously reset: ```scala mdoc:silent -class ForcedAysncReset extends MultiIOModule { +class ForcedAysncReset extends Module { // withReset's argument becomes the implicit reset in its scope withReset (reset.asAsyncReset){ val myReg = RegInit(0.U) @@ -164,7 +164,7 @@ It is **not** legal to override the reset type using last-connect semantics unless you are overriding a `DontCare`: ```scala mdoc:silent -class MyModule extends MultiIOModule { +class MyModule extends Module { val resetBool = Wire(Reset()) resetBool := DontCare resetBool := false.B // this is fine diff --git a/src/main/scala/chisel3/aop/injecting/InjectingAspect.scala b/src/main/scala/chisel3/aop/injecting/InjectingAspect.scala index f9aaceb1..39590b93 100644 --- a/src/main/scala/chisel3/aop/injecting/InjectingAspect.scala +++ b/src/main/scala/chisel3/aop/injecting/InjectingAspect.scala @@ -2,7 +2,7 @@ package chisel3.aop.injecting -import chisel3.{Module, ModuleAspect, MultiIOModule, RawModule, experimental, withClockAndReset} +import chisel3.{Module, ModuleAspect, RawModule, withClockAndReset} import chisel3.aop._ import chisel3.internal.{Builder, DynamicContext} import chisel3.internal.firrtl.DefModule @@ -63,7 +63,7 @@ abstract class InjectorAspect[T <: RawModule, M <: RawModule]( RunFirrtlTransformAnnotation(new InjectingTransform) +: modules.map { module => val (chiselIR, _) = Builder.build(Module(new ModuleAspect(module) { module match { - case x: MultiIOModule => withClockAndReset(x.clock, x.reset) { injection(module) } + case x: Module => withClockAndReset(x.clock, x.reset) { injection(module) } case x: RawModule => injection(module) } }), dynamicContext) diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala index 38ef80ba..e62cba7d 100644 --- a/src/main/scala/chisel3/compatibility.scala +++ b/src/main/scala/chisel3/compatibility.scala @@ -259,16 +259,7 @@ package object Chisel { implicit def resetToBool(reset: Reset): Bool = reset.asBool - import chisel3.experimental.Param - abstract class BlackBox(params: Map[String, Param] = Map.empty[String, Param]) extends chisel3.BlackBox(params) { - // This class auto-wraps the BlackBox with IO(...), allowing legacy code (where IO(...) wasn't - // required) to build. - override def _compatAutoWrapPorts(): Unit = { - if (!_compatIoPortBound()) { - _bindIoInPlace(io) - } - } - } + type BlackBox = chisel3.internal.LegacyBlackBox type MemBase[T <: Data] = chisel3.MemBase[T] @@ -302,35 +293,11 @@ package object Chisel { } import chisel3.CompileOptions - abstract class CompatibilityModule(implicit moduleCompileOptions: CompileOptions) - extends chisel3.internal.LegacyModule()(moduleCompileOptions) { - // This class auto-wraps the Module IO with IO(...), allowing legacy code (where IO(...) wasn't - // required) to build. - // Also provides the clock / reset constructors, which were used before withClock happened. - - // Provide a non-deprecated constructor - def this(override_clock: Option[Clock]=None, override_reset: Option[Bool]=None) - (implicit moduleCompileOptions: CompileOptions) = { - this() - this.override_clock = override_clock - this.override_reset = override_reset - } - def this(_clock: Clock)(implicit moduleCompileOptions: CompileOptions) = - this(Option(_clock), None)(moduleCompileOptions) - def this(_reset: Bool)(implicit moduleCompileOptions: CompileOptions) = - this(None, Option(_reset))(moduleCompileOptions) - def this(_clock: Clock, _reset: Bool)(implicit moduleCompileOptions: CompileOptions) = - this(Option(_clock), Option(_reset))(moduleCompileOptions) - - override def _compatAutoWrapPorts(): Unit = { - if (!_compatIoPortBound() && io != null) { - _bindIoInPlace(io) - } - } - } + @deprecated("Use Chisel.Module", "Chisel 3.5") + type CompatibilityModule = chisel3.internal.LegacyModule val Module = chisel3.Module - type Module = CompatibilityModule + type Module = chisel3.internal.LegacyModule val printf = chisel3.printf diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index c6459455..032d731d 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -21,7 +21,7 @@ abstract class ReadyValidIO[+T <: Data](gen: T) extends Bundle { // Compatibility hack for rocket-chip private val genType = (DataMirror.internal.isSynthesizable(gen), chisel3.internal.Builder.currentModule) match { - case (true, Some(module: MultiIOModule)) + case (true, Some(module: Module)) if !module.compileOptions.declaredTypeMustBeUnbound => chiselTypeOf(gen) case _ => gen } diff --git a/src/test/scala/chiselTests/AnalogIntegrationSpec.scala b/src/test/scala/chiselTests/AnalogIntegrationSpec.scala index 258b22f9..7478f2eb 100644 --- a/src/test/scala/chiselTests/AnalogIntegrationSpec.scala +++ b/src/test/scala/chiselTests/AnalogIntegrationSpec.scala @@ -31,15 +31,23 @@ class AnalogBlackBox(index: Int) extends BlackBox(Map("index" -> index)) { val io = IO(new AnalogBlackBoxIO(1)) } +// This interface exists to give a common interface type for AnalogBlackBoxModule and +// AnalogBlackBoxWrapper. This is the standard way to deal with the deprecation and removal of the +// Module.io virtual method (same for BlackBox.io). +// See https://github.com/freechipsproject/chisel3/pull/1550 for more information +trait AnalogBlackBoxModuleIntf extends Module { + def io: AnalogBlackBoxIO +} + // AnalogBlackBox wrapper, which extends Module to present the common io._ interface -class AnalogBlackBoxModule(index: Int) extends Module { +class AnalogBlackBoxModule(index: Int) extends AnalogBlackBoxModuleIntf { val io = IO(new AnalogBlackBoxIO(1)) val impl = Module(new AnalogBlackBox(index)) io <> impl.io } // Wraps up n blackboxes, connecing their buses and simply forwarding their ports up -class AnalogBlackBoxWrapper(n: Int, idxs: Seq[Int]) extends Module { +class AnalogBlackBoxWrapper(n: Int, idxs: Seq[Int]) extends AnalogBlackBoxModuleIntf { require(n > 0) val io = IO(new AnalogBlackBoxIO(n)) val bbs = idxs.map(i => Module(new AnalogBlackBoxModule(i))) diff --git a/src/test/scala/chiselTests/AutoClonetypeSpec.scala b/src/test/scala/chiselTests/AutoClonetypeSpec.scala index 6c5fd261..b791297d 100644 --- a/src/test/scala/chiselTests/AutoClonetypeSpec.scala +++ b/src/test/scala/chiselTests/AutoClonetypeSpec.scala @@ -198,7 +198,7 @@ class AutoClonetypeSpec extends ChiselFlatSpec with Utils { } "Wrapped IO construction without parent reference" should "not fail for autoclonetype" in { - class TestModule extends MultiIOModule { + class TestModule extends Module { def thunk[T](f: => T): T = f val works = thunk(IO(new Bundle { val x = Output(UInt(3.W)) @@ -208,7 +208,7 @@ class AutoClonetypeSpec extends ChiselFlatSpec with Utils { } "Wrapped IO construction with parent references" should "not fail for autoclonetype" in { - class TestModule(blah: Int) extends MultiIOModule { + class TestModule(blah: Int) extends Module { // Note that this currently fails only if f: =>T on Scala 2.11.12 // This works successfully with 2.12.11 def thunk[T](f: => T): T = f diff --git a/src/test/scala/chiselTests/BlackBox.scala b/src/test/scala/chiselTests/BlackBox.scala index 8ae7d6ee..d3d52f96 100644 --- a/src/test/scala/chiselTests/BlackBox.scala +++ b/src/test/scala/chiselTests/BlackBox.scala @@ -15,6 +15,16 @@ class BlackBoxInverter extends BlackBox { }) } +// Due to the removal of "val io", this technically works +// This style is discouraged, please use "val io" +class BlackBoxInverterSuggestName extends BlackBox { + override def desiredName: String = "BlackBoxInverter" + val foo = IO(new Bundle() { + val in = Input(Bool()) + val out = Output(Bool()) + }).suggestName("io") +} + class BlackBoxPassthrough extends BlackBox { val io = IO(new Bundle() { val in = Input(Bool()) @@ -50,6 +60,18 @@ class BlackBoxTester extends BasicTester { stop() } +class BlackBoxTesterSuggestName extends BasicTester { + val blackBoxPos = Module(new BlackBoxInverterSuggestName) + val blackBoxNeg = Module(new BlackBoxInverterSuggestName) + + blackBoxPos.foo.in := 1.U + blackBoxNeg.foo.in := 0.U + + assert(blackBoxNeg.foo.out === 1.U) + assert(blackBoxPos.foo.out === 0.U) + stop() +} + class BlackBoxFlipTester extends BasicTester { val blackBox = Module(new BlackBoxPassthrough2) @@ -187,4 +209,10 @@ class BlackBoxSpec extends ChiselFlatSpec { } ) } + "A BlackBoxed using suggestName(\"io\")" should "work (but don't do this)" in { + assertTesterPasses( + {new BlackBoxTesterSuggestName}, + Seq("/chisel3/BlackBoxTest.v"), + TesterDriver.verilatorOnly) + } } diff --git a/src/test/scala/chiselTests/BoringUtilsSpec.scala b/src/test/scala/chiselTests/BoringUtilsSpec.scala index 0500ac23..39859581 100644 --- a/src/test/scala/chiselTests/BoringUtilsSpec.scala +++ b/src/test/scala/chiselTests/BoringUtilsSpec.scala @@ -71,7 +71,7 @@ class BoringUtilsSpec extends ChiselFlatSpec with ChiselRunners { out := x } - class Top(val width: Int) extends MultiIOModule { + class Top(val width: Int) extends Module { /* From the perspective of deduplication, all sources are identical and all sinks are identical. */ val sources = Seq.fill(3)(Module(new Source)) val sinks = Seq.fill(6)(Module(new Sink)) diff --git a/src/test/scala/chiselTests/CloneModuleSpec.scala b/src/test/scala/chiselTests/CloneModuleSpec.scala index 7f3ef854..e54ef1c2 100644 --- a/src/test/scala/chiselTests/CloneModuleSpec.scala +++ b/src/test/scala/chiselTests/CloneModuleSpec.scala @@ -8,7 +8,7 @@ import chisel3.util.{Queue, EnqIO, DeqIO, QueueIO, log2Ceil} import chisel3.experimental.{CloneModuleAsRecord, IO} import chisel3.testers.BasicTester -class MultiIOQueue[T <: Data](gen: T, val entries: Int) extends MultiIOModule { +class MultiIOQueue[T <: Data](gen: T, val entries: Int) extends Module { val clk = IO(Input(Clock())) val rst = IO(Input(Reset())) val enq = IO(Flipped(EnqIO(gen))) diff --git a/src/test/scala/chiselTests/CompatibilitySpec.scala b/src/test/scala/chiselTests/CompatibilitySpec.scala index 50213d4d..6a77c821 100644 --- a/src/test/scala/chiselTests/CompatibilitySpec.scala +++ b/src/test/scala/chiselTests/CompatibilitySpec.scala @@ -239,6 +239,20 @@ class CompatibiltySpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyCheck ChiselStage.elaborate { new RequireIOWrapModule() } } + "A Module without val io" should "throw an exception" in { + class ModuleWithoutValIO extends Module { + val foo = new Bundle { + val in = UInt(width = 32).asInput + val out = Bool().asOutput + } + foo.out := foo.in(1) + } + val e = intercept[Exception]( + ChiselStage.elaborate { new ModuleWithoutValIO } + ) + e.getMessage should include("must have a 'val io' Bundle") + } + "A Module connecting output as source to input as sink when compiled with the Chisel compatibility package" should "not throw an exception" in { class SimpleModule extends Module { diff --git a/src/test/scala/chiselTests/DataPrint.scala b/src/test/scala/chiselTests/DataPrint.scala index beb92f0d..b5f96c4d 100644 --- a/src/test/scala/chiselTests/DataPrint.scala +++ b/src/test/scala/chiselTests/DataPrint.scala @@ -34,7 +34,7 @@ class DataPrintSpec extends ChiselFlatSpec with Matchers { } } } - class BoundDataModule extends MultiIOModule { // not in the test to avoid anon naming suffixes + class BoundDataModule extends Module { // not in the test to avoid anon naming suffixes Wire(UInt()).toString should be("UInt(Wire in BoundDataModule)") Reg(SInt()).toString should be("SInt(Reg in BoundDataModule)") val io = IO(Output(Bool())) // needs a name so elaboration doesn't fail @@ -44,7 +44,7 @@ class DataPrintSpec extends ChiselFlatSpec with Matchers { (2.U + 2.U).toString should be("UInt<2>(OpResult in BoundDataModule)") Wire(Vec(3, UInt(2.W))).toString should be ("UInt<2>[3](Wire in BoundDataModule)") - class InnerModule extends MultiIOModule { + class InnerModule extends Module { val io = IO(Output(new Bundle { val a = UInt(4.W) })) diff --git a/src/test/scala/chiselTests/Direction.scala b/src/test/scala/chiselTests/Direction.scala index 570abc68..39ff1f0e 100644 --- a/src/test/scala/chiselTests/Direction.scala +++ b/src/test/scala/chiselTests/Direction.scala @@ -131,7 +131,7 @@ class DirectionSpec extends ChiselPropSpec with Matchers with Utils { import chisel3.experimental.{DataMirror, Direction} property("Directions should be preserved through cloning and binding of Bundles") { - ChiselStage.elaborate(new MultiIOModule { + ChiselStage.elaborate(new Module { class MyBundle extends Bundle { val foo = Input(UInt(8.W)) val bar = Output(UInt(8.W)) @@ -164,11 +164,11 @@ class DirectionSpec extends ChiselPropSpec with Matchers with Utils { for ((data, dir) <- actualDirs) { DataMirror.directionOf(data) shouldBe (dir) } - }.asInstanceOf[MultiIOModule]) // The cast works around weird reflection behavior (bug?) + }.asInstanceOf[Module]) // The cast works around weird reflection behavior (bug?) } property("Directions should be preserved through cloning and binding of Vecs") { - ChiselStage.elaborate(new MultiIOModule { + ChiselStage.elaborate(new Module { val a = Vec(1, Input(UInt(8.W))) val b = Vec(1, a) val c = Vec(1, Flipped(a)) @@ -197,7 +197,7 @@ class DirectionSpec extends ChiselPropSpec with Matchers with Utils { for ((data, dir) <- actualDirs) { DataMirror.directionOf(data) shouldBe (dir) } - }.asInstanceOf[MultiIOModule]) // The cast works around weird reflection behavior (bug?) + }.asInstanceOf[Module]) // The cast works around weird reflection behavior (bug?) } property("Using Vec and Flipped together should calculate directions properly") { diff --git a/src/test/scala/chiselTests/DriverSpec.scala b/src/test/scala/chiselTests/DriverSpec.scala index e78185a1..3a78683b 100644 --- a/src/test/scala/chiselTests/DriverSpec.scala +++ b/src/test/scala/chiselTests/DriverSpec.scala @@ -19,7 +19,7 @@ class DummyModule extends Module { io.out := io.in } -class TypeErrorModule extends chisel3.MultiIOModule { +class TypeErrorModule extends chisel3.Module { val in = IO(Input(UInt(1.W))) val out = IO(Output(SInt(1.W))) out := in diff --git a/src/test/scala/chiselTests/Module.scala b/src/test/scala/chiselTests/Module.scala index 03239785..932c94a5 100644 --- a/src/test/scala/chiselTests/Module.scala +++ b/src/test/scala/chiselTests/Module.scala @@ -143,7 +143,7 @@ class ModuleSpec extends ChiselPropSpec with Utils { property("DataMirror.modulePorts should work") { ChiselStage.elaborate(new Module { val io = IO(new Bundle { }) - val m = Module(new chisel3.MultiIOModule { + val m = Module(new chisel3.Module { val a = IO(UInt(8.W)) val b = IO(Bool()) }) diff --git a/src/test/scala/chiselTests/MultiIOModule.scala b/src/test/scala/chiselTests/MultiIOModule.scala index d9eda807..9abf324b 100644 --- a/src/test/scala/chiselTests/MultiIOModule.scala +++ b/src/test/scala/chiselTests/MultiIOModule.scala @@ -5,7 +5,7 @@ package chiselTests import chisel3._ import chisel3.testers.BasicTester -class MultiIOPlusOne extends MultiIOModule { +class MultiIOPlusOne extends Module { val in = IO(Input(UInt(32.W))) val out = IO(Output(UInt(32.W))) @@ -20,20 +20,20 @@ class MultiIOTester extends BasicTester { } // Demonstrate multiple IOs with inheritance where the IO is assigned to internally -trait LiteralOutputTrait extends MultiIOModule { +trait LiteralOutputTrait extends Module { val myLiteralIO = IO(Output(UInt(32.W))) myLiteralIO := 2.U } // Demonstrate multiple IOs with inheritance where the IO is not assigned // (and must be assigned by what extends this trait). -trait MultiIOTrait extends MultiIOModule { +trait MultiIOTrait extends Module { val myTraitIO = IO(Output(UInt(32.W))) } // Composition of the two above traits, example of IO composition directly using multiple top-level // IOs rather than indirectly by constraining the type of the single .io field. -class ComposedMultiIOModule extends MultiIOModule +class ComposedMultiIOModule extends Module with LiteralOutputTrait with MultiIOTrait { val topModuleIO = IO(Input(UInt(32.W))) myTraitIO := topModuleIO diff --git a/src/test/scala/chiselTests/NamingAnnotationTest.scala b/src/test/scala/chiselTests/NamingAnnotationTest.scala index 43ec837d..2226a48a 100644 --- a/src/test/scala/chiselTests/NamingAnnotationTest.scala +++ b/src/test/scala/chiselTests/NamingAnnotationTest.scala @@ -9,7 +9,7 @@ import chisel3.stage.ChiselStage import scala.collection.mutable.ListBuffer -trait NamedModuleTester extends MultiIOModule { +trait NamedModuleTester extends Module { val expectedNameMap = ListBuffer[(InstanceId, String)]() val expectedModuleNameMap = ListBuffer[(Module, String)]() diff --git a/src/test/scala/chiselTests/QueueSpec.scala b/src/test/scala/chiselTests/QueueSpec.scala index ad14ea15..9dc7f120 100644 --- a/src/test/scala/chiselTests/QueueSpec.scala +++ b/src/test/scala/chiselTests/QueueSpec.scala @@ -272,7 +272,7 @@ class QueueSpec extends ChiselPropSpec { } property("Queue.irrevocable should elaborate") { - class IrrevocableQueue extends MultiIOModule { + class IrrevocableQueue extends Module { val in = Wire(Decoupled(Bool())) val iQueue = Queue.irrevocable(in, 1) } diff --git a/src/test/scala/chiselTests/ResetSpec.scala b/src/test/scala/chiselTests/ResetSpec.scala index 77c90814..0e535964 100644 --- a/src/test/scala/chiselTests/ResetSpec.scala +++ b/src/test/scala/chiselTests/ResetSpec.scala @@ -73,14 +73,14 @@ class ResetSpec extends ChiselFlatSpec with Utils { behavior of "Users" they should "be able to force implicit reset to be synchronous" in { - val fir = ChiselStage.emitChirrtl(new MultiIOModule with RequireSyncReset { + val fir = ChiselStage.emitChirrtl(new Module with RequireSyncReset { reset shouldBe a [Bool] }) fir should include ("input reset : UInt<1>") } they should "be able to force implicit reset to be asynchronous" in { - val fir = ChiselStage.emitChirrtl(new MultiIOModule with RequireAsyncReset { + val fir = ChiselStage.emitChirrtl(new Module with RequireAsyncReset { reset shouldBe an [AsyncReset] }) fir should include ("input reset : AsyncReset") @@ -88,8 +88,8 @@ class ResetSpec extends ChiselFlatSpec with Utils { "Chisel" should "error if sync and async modules are nested" in { a [ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate(new MultiIOModule with RequireAsyncReset { - val mod = Module(new MultiIOModule with RequireSyncReset) + ChiselStage.elaborate(new Module with RequireAsyncReset { + val mod = Module(new Module with RequireSyncReset) }) } } diff --git a/src/test/scala/chiselTests/StrongEnum.scala b/src/test/scala/chiselTests/StrongEnum.scala index d742903c..bf0eb2fe 100644 --- a/src/test/scala/chiselTests/StrongEnum.scala +++ b/src/test/scala/chiselTests/StrongEnum.scala @@ -77,7 +77,7 @@ class CastFromNonLit extends Module { class CastFromNonLitWidth(w: Option[Int] = None) extends Module { val width = if (w.isDefined) w.get.W else UnknownWidth() - override val io = IO(new Bundle { + val io = IO(new Bundle { val in = Input(UInt(width)) val out = Output(EnumExample()) }) diff --git a/src/test/scala/chiselTests/Util.scala b/src/test/scala/chiselTests/Util.scala index d5929dcb..e8354b8d 100644 --- a/src/test/scala/chiselTests/Util.scala +++ b/src/test/scala/chiselTests/Util.scala @@ -20,7 +20,7 @@ trait AbstractPassthroughModule extends RawModule { } class PassthroughModule extends Module with AbstractPassthroughModule -class PassthroughMultiIOModule extends MultiIOModule with AbstractPassthroughModule +class PassthroughMultiIOModule extends Module with AbstractPassthroughModule class PassthroughRawModule extends RawModule with AbstractPassthroughModule case class ScalaIntervalSimulator(intervalRange: IntervalRange) { diff --git a/src/test/scala/chiselTests/experimental/ForceNames.scala b/src/test/scala/chiselTests/experimental/ForceNames.scala index d4ad4d67..b3534f11 100644 --- a/src/test/scala/chiselTests/experimental/ForceNames.scala +++ b/src/test/scala/chiselTests/experimental/ForceNames.scala @@ -14,7 +14,7 @@ import logger.{LogLevel, LogLevelAnnotation} /** Object containing Modules used for testing */ object ForceNamesHierarchy { - class WrapperExample extends MultiIOModule { + class WrapperExample extends Module { val in = IO(Input(UInt(3.W))) val out = IO(Output(UInt(3.W))) val inst = Module(new Wrapper) @@ -22,7 +22,7 @@ object ForceNamesHierarchy { out := inst.out forceName(out, "outt") } - class Wrapper extends MultiIOModule with InlineInstance { + class Wrapper extends Module with InlineInstance { val in = IO(Input(UInt(3.W))) val out = IO(Output(UInt(3.W))) val inst = Module(new MyLeaf) @@ -30,12 +30,12 @@ object ForceNamesHierarchy { inst.in := in out := inst.out } - class MyLeaf extends MultiIOModule { + class MyLeaf extends Module { val in = IO(Input(UInt(3.W))) val out = IO(Output(UInt(3.W))) out := in } - class RenamePortsExample extends MultiIOModule { + class RenamePortsExample extends Module { val in = IO(Input(UInt(3.W))) val out = IO(Output(UInt(3.W))) val inst = Module(new MyLeaf) @@ -43,13 +43,13 @@ object ForceNamesHierarchy { out := inst.out forceName(inst.in, "inn") } - class ConflictingName extends MultiIOModule { + class ConflictingName extends Module { val in = IO(Input(UInt(3.W))) val out = IO(Output(UInt(3.W))) out := in forceName(out, "in") } - class BundleName extends MultiIOModule { + class BundleName extends Module { val in = IO(new Bundle { val a = Input(UInt(3.W)) val b = Input(UInt(3.W)) diff --git a/src/test/scala/chiselTests/experimental/ProgrammaticPortsSpec.scala b/src/test/scala/chiselTests/experimental/ProgrammaticPortsSpec.scala index ffbdb814..ffe3a37f 100644 --- a/src/test/scala/chiselTests/experimental/ProgrammaticPortsSpec.scala +++ b/src/test/scala/chiselTests/experimental/ProgrammaticPortsSpec.scala @@ -52,12 +52,11 @@ class ProgrammaticPortsSpec extends ChiselFlatSpec with Utils { doTest(new PortsWinTester) } - "LegacyModule" should "ignore suggestName on ports" in { + "Module" should "ignore suggestName on clock and reset" in { doTest(new Module with NamedModuleTester { val io = IO(new Bundle { val foo = Output(UInt(8.W)) }) - expectName(io.suggestName("cheese"), "io") expectName(clock.suggestName("tart"), "clock") expectName(reset.suggestName("teser"), "reset") }) @@ -65,7 +64,7 @@ class ProgrammaticPortsSpec extends ChiselFlatSpec with Utils { "SuggestName collisions on ports" should "be illegal" in { a [ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate(new MultiIOModule { + ChiselStage.elaborate(new Module { val foo = IO(UInt(8.W)).suggestName("apple") val bar = IO(UInt(8.W)).suggestName("apple") }) diff --git a/src/test/scala/chiselTests/naming/NamePluginSpec.scala b/src/test/scala/chiselTests/naming/NamePluginSpec.scala index 5e7133d1..3a539bd4 100644 --- a/src/test/scala/chiselTests/naming/NamePluginSpec.scala +++ b/src/test/scala/chiselTests/naming/NamePluginSpec.scala @@ -11,7 +11,7 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { implicit val minimumScalaVersion: Int = 12 "Scala plugin" should "name internally scoped components" in { - class Test extends MultiIOModule { + class Test extends Module { { val mywire = Wire(UInt(3.W))} } aspectTest(() => new Test) { @@ -20,8 +20,8 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { } "Scala plugin" should "name internally scoped instances" in { - class Inner extends MultiIOModule { } - class Test extends MultiIOModule { + class Inner extends Module { } + class Test extends Module { { val myinstance = Module(new Inner) } } aspectTest(() => new Test) { @@ -30,7 +30,7 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { } "Scala plugin" should "interact with prefixing" in { - class Test extends MultiIOModule { + class Test extends Module { def builder() = { val wire = Wire(UInt(3.W)) } @@ -47,7 +47,7 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { } "Scala plugin" should "interact with prefixing so last val name wins" in { - class Test extends MultiIOModule { + class Test extends Module { def builder() = { val wire1 = Wire(UInt(3.W)) val wire2 = Wire(UInt(3.W)) @@ -71,7 +71,7 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { "Naming on option" should "work" in { - class Test extends MultiIOModule { + class Test extends Module { def builder(): Option[UInt] = { val a = Wire(UInt(3.W)) Some(a) @@ -88,7 +88,7 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { "Naming on iterables" should "work" in { - class Test extends MultiIOModule { + class Test extends Module { def builder(): Seq[UInt] = { val a = Wire(UInt(3.W)) val b = Wire(UInt(3.W)) @@ -108,7 +108,7 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { "Naming on nested iterables" should "work" in { - class Test extends MultiIOModule { + class Test extends Module { def builder(): Seq[Seq[UInt]] = { val a = Wire(UInt(3.W)) val b = Wire(UInt(3.W)) @@ -137,7 +137,7 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { "Naming on custom case classes" should "not work" in { case class Container(a: UInt, b: UInt) - class Test extends MultiIOModule { + class Test extends Module { def builder(): Container = { val a = Wire(UInt(3.W)) val b = Wire(UInt(3.W)) @@ -167,7 +167,7 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { } "Multiple names on a non-IO" should "get the first name" in { - class Test extends MultiIOModule { + class Test extends Module { { val a = Wire(UInt(3.W)) val b = a @@ -234,7 +234,7 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { "autoSeed" should "override automatic naming for non-IO" in { - class Test extends MultiIOModule { + class Test extends Module { { val a = Wire(UInt(3.W)) a.autoSeed("b") @@ -248,7 +248,7 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { } "Unapply assignments" should "still be named" in { - class Test extends MultiIOModule { + class Test extends Module { { val (a, b) = (Wire(UInt(3.W)), Wire(UInt(3.W))) } @@ -261,7 +261,7 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { } "Unapply assignments" should "not override already named things" in { - class Test extends MultiIOModule { + class Test extends Module { { val x = Wire(UInt(3.W)) val (a, b) = (x, Wire(UInt(3.W))) @@ -276,7 +276,7 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { "Case class unapply assignments" should "be named" in { case class Foo(x: UInt, y: UInt) - class Test extends MultiIOModule { + class Test extends Module { { def func() = Foo(Wire(UInt(3.W)), Wire(UInt(3.W))) val Foo(a, b) = func() @@ -291,7 +291,7 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { "Complex unapply assignments" should "be named" in { case class Foo(x: UInt, y: UInt) - class Test extends MultiIOModule { + class Test extends Module { { val w = Wire(UInt(3.W)) def func() = { @@ -320,7 +320,7 @@ class NamePluginSpec extends ChiselFlatSpec with Utils { } "Nested val declarations" should "all be named" in { - class Test extends MultiIOModule { + class Test extends Module { { val a = { val b = { diff --git a/src/test/scala/chiselTests/naming/PrefixSpec.scala b/src/test/scala/chiselTests/naming/PrefixSpec.scala index 83408dea..0712692d 100644 --- a/src/test/scala/chiselTests/naming/PrefixSpec.scala +++ b/src/test/scala/chiselTests/naming/PrefixSpec.scala @@ -10,7 +10,7 @@ import chiselTests.{ChiselPropSpec, Utils} class PrefixSpec extends ChiselPropSpec with Utils { implicit val minimumMajorVersion: Int = 12 property("Scala plugin should interact with prefixing so last plugin name wins?") { - class Test extends MultiIOModule { + class Test extends Module { def builder(): UInt = { val wire1 = Wire(UInt(3.W)) val wire2 = Wire(UInt(3.W)) @@ -34,7 +34,7 @@ class PrefixSpec extends ChiselPropSpec with Utils { } property("Nested prefixes should work") { - class Test extends MultiIOModule { + class Test extends Module { def builder2(): UInt = { val wire1 = Wire(UInt(3.W)) val wire2 = Wire(UInt(3.W)) @@ -68,7 +68,7 @@ class PrefixSpec extends ChiselPropSpec with Utils { } property("Prefixing seeded with signal") { - class Test extends MultiIOModule { + class Test extends Module { def builder(): UInt = { val wire = Wire(UInt(3.W)) wire := 3.U @@ -93,7 +93,7 @@ class PrefixSpec extends ChiselPropSpec with Utils { property("Automatic prefixing should work") { - class Test extends MultiIOModule { + class Test extends Module { def builder(): UInt = { val a = Wire(UInt(3.W)) val b = Wire(UInt(3.W)) @@ -113,7 +113,7 @@ class PrefixSpec extends ChiselPropSpec with Utils { property("No prefixing annotation on defs should work") { - class Test extends MultiIOModule { + class Test extends Module { def builder(): UInt = noPrefix { val a = Wire(UInt(3.W)) val b = Wire(UInt(3.W)) @@ -130,7 +130,7 @@ class PrefixSpec extends ChiselPropSpec with Utils { property("Prefixing on temps should work") { - class Test extends MultiIOModule { + class Test extends Module { def builder(): UInt = { val a = Wire(UInt(3.W)) val b = Wire(UInt(3.W)) @@ -149,13 +149,13 @@ class PrefixSpec extends ChiselPropSpec with Utils { } property("Prefixing should not leak into child modules") { - class Child extends MultiIOModule { + class Child extends Module { { val wire = Wire(UInt()) } } - class Test extends MultiIOModule { + class Test extends Module { { val child = prefix("InTest") { Module(new Child) @@ -169,13 +169,13 @@ class PrefixSpec extends ChiselPropSpec with Utils { } property("Prefixing should not leak into child modules, example 2") { - class Child extends MultiIOModule { + class Child extends Module { { val wire = Wire(UInt()) } } - class Test extends MultiIOModule { + class Test extends Module { val x = IO(Input(UInt(3.W))) val y = { lazy val module = new Child @@ -189,13 +189,13 @@ class PrefixSpec extends ChiselPropSpec with Utils { } property("Instance names should not be added to prefix") { - class Child(tpe: UInt) extends MultiIOModule { + class Child(tpe: UInt) extends Module { { val io = IO(Input(tpe)) } } - class Test extends MultiIOModule { + class Test extends Module { { lazy val module = { val x = UInt(3.W) @@ -212,7 +212,7 @@ class PrefixSpec extends ChiselPropSpec with Utils { property("Prefixing should not be caused by nested Iterable[Iterable[Any]]") { - class Test extends MultiIOModule { + class Test extends Module { { val iia = { val wire = Wire(UInt(3.W)) @@ -227,7 +227,7 @@ class PrefixSpec extends ChiselPropSpec with Utils { } property("Prefixing should be caused by nested Iterable[Iterable[Data]]") { - class Test extends MultiIOModule { + class Test extends Module { { val iia = { val wire = Wire(UInt(3.W)) @@ -242,7 +242,7 @@ class PrefixSpec extends ChiselPropSpec with Utils { } property("Prefixing should be the prefix during the last call to autoName/suggestName") { - class Test extends MultiIOModule { + class Test extends Module { { val wire = { val x = Wire(UInt(3.W)).suggestName("mywire") @@ -258,7 +258,7 @@ class PrefixSpec extends ChiselPropSpec with Utils { } property("Prefixing have intuitive behavior") { - class Test extends MultiIOModule { + class Test extends Module { { val wire = { val x = Wire(UInt(3.W)).suggestName("mywire") @@ -274,7 +274,7 @@ class PrefixSpec extends ChiselPropSpec with Utils { } property("Prefixing on connection to subfields work") { - class Test extends MultiIOModule { + class Test extends Module { { val wire = Wire(new Bundle { val x = UInt(3.W) @@ -301,12 +301,12 @@ class PrefixSpec extends ChiselPropSpec with Utils { } property("Prefixing on connection to IOs should work") { - class Child extends MultiIOModule { + class Child extends Module { val in = IO(Input(UInt(3.W))) val out = IO(Output(UInt(3.W))) out := RegNext(in) } - class Test extends MultiIOModule { + class Test extends Module { { val child = Module(new Child) child.in := RegNext(3.U) @@ -324,12 +324,12 @@ class PrefixSpec extends ChiselPropSpec with Utils { } property("Prefixing on bulk connects should work") { - class Child extends MultiIOModule { + class Child extends Module { val in = IO(Input(UInt(3.W))) val out = IO(Output(UInt(3.W))) out := RegNext(in) } - class Test extends MultiIOModule { + class Test extends Module { { val child = Module(new Child) child.in <> RegNext(3.U) @@ -347,7 +347,7 @@ class PrefixSpec extends ChiselPropSpec with Utils { } property("Connections should use the non-prefixed name of the connected Data") { - class Test extends MultiIOModule { + class Test extends Module { prefix("foo") { val x = Wire(UInt(8.W)) x := { @@ -364,7 +364,7 @@ class PrefixSpec extends ChiselPropSpec with Utils { } property("Connections to aggregate fields should use the non-prefixed aggregate name") { - class Test extends MultiIOModule { + class Test extends Module { prefix("foo") { val x = Wire(new Bundle { val bar = UInt(8.W) }) x.bar := { @@ -382,7 +382,7 @@ class PrefixSpec extends ChiselPropSpec with Utils { property("Prefixing with wires in recursive functions should grow linearly") { - class Test extends MultiIOModule { + class Test extends Module { def func(bools: Seq[Bool]): Bool = { if (bools.isEmpty) true.B else { diff --git a/src/test/scala/chiselTests/stage/ChiselMainSpec.scala b/src/test/scala/chiselTests/stage/ChiselMainSpec.scala index a11b8a44..0fc42fc6 100644 --- a/src/test/scala/chiselTests/stage/ChiselMainSpec.scala +++ b/src/test/scala/chiselTests/stage/ChiselMainSpec.scala @@ -24,7 +24,7 @@ object ChiselMainSpec { } /** A module that connects two of the same types together */ - class SameTypesModule extends MultiIOModule { + class SameTypesModule extends Module { val in = IO(Input(UInt(1.W))) val out = IO(Output(UInt(1.W))) out := in diff --git a/src/test/scala/chiselTests/stage/ChiselStageSpec.scala b/src/test/scala/chiselTests/stage/ChiselStageSpec.scala index fb5698a6..98bbb2ea 100644 --- a/src/test/scala/chiselTests/stage/ChiselStageSpec.scala +++ b/src/test/scala/chiselTests/stage/ChiselStageSpec.scala @@ -15,13 +15,13 @@ import firrtl.options.Dependency object ChiselStageSpec { - class Bar extends MultiIOModule { + class Bar extends Module { val in = IO(Input(UInt(4.W))) val out = IO(Output(UInt(4.W))) out := ~in } - class Foo extends MultiIOModule { + class Foo extends Module { val addr = IO(Input(UInt(4.W))) val out = IO(Output(Bool())) val memory = SyncReadMem(8, Bool()) diff --git a/src/test/scala/chiselTests/util/CatSpec.scala b/src/test/scala/chiselTests/util/CatSpec.scala index 2e52fe63..5565ca51 100644 --- a/src/test/scala/chiselTests/util/CatSpec.scala +++ b/src/test/scala/chiselTests/util/CatSpec.scala @@ -10,7 +10,7 @@ import chiselTests.ChiselFlatSpec object CatSpec { - class JackIsATypeSystemGod extends MultiIOModule { + class JackIsATypeSystemGod extends Module { val in = IO(Input (Vec(0, UInt(8.W)))) val out = IO(Output(UInt(8.W))) |
