diff options
Diffstat (limited to 'src')
174 files changed, 925 insertions, 28172 deletions
diff --git a/src/main/scala/chisel3/aop/AspectLibrary.scala b/src/main/scala/chisel3/aop/AspectLibrary.scala index 04ac2384..fb6a2dbc 100644 --- a/src/main/scala/chisel3/aop/AspectLibrary.scala +++ b/src/main/scala/chisel3/aop/AspectLibrary.scala @@ -1,53 +1,53 @@ -// SPDX-License-Identifier: Apache-2.0 +// // SPDX-License-Identifier: Apache-2.0 -package chisel3.aop +// package chisel3.aop -import chisel3.RawModule -import firrtl.options.{OptionsException, RegisteredLibrary, ShellOption} +// import chisel3.RawModule +// import firrtl.options.{OptionsException, RegisteredLibrary, ShellOption} -/** Enables adding aspects to a design from the commandline, e.g. - * sbt> runMain chisel3.stage.ChiselMain --module <module> --with-aspect <aspect> - */ -final class AspectLibrary() extends RegisteredLibrary { - val name = "AspectLibrary" +// /** Enables adding aspects to a design from the commandline, e.g. +// * sbt> runMain chisel3.stage.ChiselMain --module <module> --with-aspect <aspect> +// */ +// final class AspectLibrary() extends RegisteredLibrary { +// val name = "AspectLibrary" - import scala.reflect.runtime.universe._ +// import scala.reflect.runtime.universe._ - private def apply(aspectName: String): Aspect[RawModule] = { - try { - // If a regular class, instantiate, otherwise try as a singleton object - try { - val x = Class.forName(aspectName).asInstanceOf[Class[_ <: Aspect[RawModule]]] - x.newInstance() - } catch { - case e: InstantiationException => - val rm = runtimeMirror(getClass.getClassLoader) - val x = rm.staticModule(aspectName) - try { - rm.reflectModule(x).instance.asInstanceOf[Aspect[RawModule]] - } catch { - case _: Exception => throw e - } - } - } catch { - case e: ClassNotFoundException => - throw new OptionsException(s"Unable to locate aspect '$aspectName'! (Did you misspell it?)", e) - case e: InstantiationException => - throw new OptionsException( - s"Unable to create instance of aspect '$aspectName'! (Does this class take parameters?)", - e - ) - } - } +// private def apply(aspectName: String): Aspect[RawModule] = { +// try { +// // If a regular class, instantiate, otherwise try as a singleton object +// try { +// val x = Class.forName(aspectName).asInstanceOf[Class[_ <: Aspect[RawModule]]] +// x.newInstance() +// } catch { +// case e: InstantiationException => +// val rm = runtimeMirror(getClass.getClassLoader) +// val x = rm.staticModule(aspectName) +// try { +// rm.reflectModule(x).instance.asInstanceOf[Aspect[RawModule]] +// } catch { +// case _: Exception => throw e +// } +// } +// } catch { +// case e: ClassNotFoundException => +// throw new OptionsException(s"Unable to locate aspect '$aspectName'! (Did you misspell it?)", e) +// case e: InstantiationException => +// throw new OptionsException( +// s"Unable to create instance of aspect '$aspectName'! (Does this class take parameters?)", +// e +// ) +// } +// } - val options = Seq( - new ShellOption[String]( - longOption = "with-aspect", - toAnnotationSeq = { - case aspectName: String => Seq(apply(aspectName)) - }, - helpText = "The name/class of an aspect to compile with (must be a class/object without arguments!)", - helpValueName = Some("<package>.<aspect>") - ) - ) -} +// val options = Seq( +// new ShellOption[String]( +// longOption = "with-aspect", +// toAnnotationSeq = { +// case aspectName: String => Seq(apply(aspectName)) +// }, +// helpText = "The name/class of an aspect to compile with (must be a class/object without arguments!)", +// helpValueName = Some("<package>.<aspect>") +// ) +// ) +// } diff --git a/src/main/scala/chisel3/aop/Select.scala b/src/main/scala/chisel3/aop/Select.scala index 738d6f31..19317f2a 100644 --- a/src/main/scala/chisel3/aop/Select.scala +++ b/src/main/scala/chisel3/aop/Select.scala @@ -1,614 +1,614 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chisel3.aop - -import chisel3._ -import chisel3.internal.{HasId} -import chisel3.experimental.BaseModule -import chisel3.experimental.FixedPoint -import chisel3.internal.firrtl.{Definition => DefinitionIR, _} -import chisel3.experimental.hierarchy._ -import chisel3.internal.PseudoModule -import chisel3.internal.BaseModule.ModuleClone -import firrtl.annotations.ReferenceTarget -import scala.reflect.runtime.universe.TypeTag - -import scala.collection.mutable -import chisel3.internal.naming.chiselName - -/** Use to select Chisel components in a module, after that module has been constructed - * Useful for adding additional Chisel annotations or for use within an [[Aspect]] - */ -object Select { - - /** Return just leaf components of expanded node - * - * @param d Component to find leafs if aggregate typed. Intermediate fields/indicies are not included - */ - def getLeafs(d: Data): Seq[Data] = d match { - case r: Record => r.elementsIterator.flatMap(getLeafs).toSeq - case v: Vec[_] => v.getElements.flatMap(getLeafs) - case other => Seq(other) - } - - /** Return all expanded components, including intermediate aggregate nodes - * - * @param d Component to find leafs if aggregate typed. Intermediate fields/indicies ARE included - */ - def getIntermediateAndLeafs(d: Data): Seq[Data] = d match { - case r: Record => r +: r.elementsIterator.flatMap(getIntermediateAndLeafs).toSeq - case v: Vec[_] => v +: v.getElements.flatMap(getIntermediateAndLeafs) - case other => Seq(other) - } - - /** Selects all instances/modules directly instantiated within given definition - * - * @param parent - */ - def instancesIn(parent: Hierarchy[BaseModule]): Seq[Instance[BaseModule]] = { - check(parent) - implicit val mg = new chisel3.internal.MacroGenerated {} - parent.proto._component.get match { - case d: DefModule => - d.commands.collect { - case d: DefInstance => - d.id match { - case p: chisel3.internal.BaseModule.IsClone[_] => - parent._lookup { x => new Instance(Clone(p)).asInstanceOf[Instance[BaseModule]] } - case other: BaseModule => - parent._lookup { x => other } - } - } - case other => Nil - } - } - - /** Selects all Instances of instances/modules directly instantiated within given module, of provided type - * - * @note IMPORTANT: this function requires summoning a TypeTag[T], which will fail if T is an inner class. - * @note IMPORTANT: this function ignores type parameters. E.g. instancesOf[List[Int]] would return List[String]. - * - * @param parent hierarchy which instantiates the returned Definitions - */ - def instancesOf[T <: BaseModule: TypeTag](parent: Hierarchy[BaseModule]): Seq[Instance[T]] = { - check(parent) - implicit val mg = new chisel3.internal.MacroGenerated {} - parent.proto._component.get match { - case d: DefModule => - d.commands.flatMap { - case d: DefInstance => - d.id match { - case p: chisel3.internal.BaseModule.IsClone[_] => - val i = parent._lookup { x => new Instance(Clone(p)).asInstanceOf[Instance[BaseModule]] } - if (i.isA[T]) Some(i.asInstanceOf[Instance[T]]) else None - case other: BaseModule => - val i = parent._lookup { x => other } - if (i.isA[T]) Some(i.asInstanceOf[Instance[T]]) else None - } - case other => None - } - case other => Nil - } - } - - /** Selects all Instances directly and indirectly instantiated within given root hierarchy, of provided type - * - * @note IMPORTANT: this function requires summoning a TypeTag[T], which will fail if T is an inner class. - * @note IMPORTANT: this function ignores type parameters. E.g. allInstancesOf[List[Int]] would return List[String]. - * - * @param root top of the hierarchy to search for instances/modules of given type - */ - def allInstancesOf[T <: BaseModule: TypeTag](root: Hierarchy[BaseModule]): Seq[Instance[T]] = { - val soFar = if (root.isA[T]) Seq(root.toInstance.asInstanceOf[Instance[T]]) else Nil - val allLocalInstances = instancesIn(root) - soFar ++ (allLocalInstances.flatMap(allInstancesOf[T])) - } - - /** Selects the Definitions of all instances/modules directly instantiated within given module - * - * @param parent - */ - def definitionsIn(parent: Hierarchy[BaseModule]): Seq[Definition[BaseModule]] = { - type DefType = Definition[BaseModule] - implicit val mg = new chisel3.internal.MacroGenerated {} - check(parent) - val defs = parent.proto._component.get match { - case d: DefModule => - d.commands.collect { - case i: DefInstance => - i.id match { - case p: chisel3.internal.BaseModule.IsClone[_] => - parent._lookup { x => new Definition(Proto(p.getProto)).asInstanceOf[Definition[BaseModule]] } - case other: BaseModule => - parent._lookup { x => other.toDefinition } - } - } - case other => Nil - } - val (_, defList) = defs.foldLeft((Set.empty[DefType], List.empty[DefType])) { - case ((set, list), definition: Definition[BaseModule]) => - if (set.contains(definition)) (set, list) else (set + definition, definition +: list) - } - defList.reverse - } - - /** Selects all Definitions of instances/modules directly instantiated within given module, of provided type - * - * @note IMPORTANT: this function requires summoning a TypeTag[T], which will fail if T is an inner class. - * @note IMPORTANT: this function ignores type parameters. E.g. definitionsOf[List[Int]] would return List[String]. - * - * @param parent hierarchy which instantiates the returned Definitions - */ - def definitionsOf[T <: BaseModule: TypeTag](parent: Hierarchy[BaseModule]): Seq[Definition[T]] = { - check(parent) - implicit val mg = new chisel3.internal.MacroGenerated {} - type DefType = Definition[T] - val defs = parent.proto._component.get match { - case d: DefModule => - d.commands.flatMap { - case d: DefInstance => - d.id match { - case p: chisel3.internal.BaseModule.IsClone[_] => - val d = parent._lookup { x => new Definition(Clone(p)).asInstanceOf[Definition[BaseModule]] } - if (d.isA[T]) Some(d.asInstanceOf[Definition[T]]) else None - case other: BaseModule => - val d = parent._lookup { x => other.toDefinition } - if (d.isA[T]) Some(d.asInstanceOf[Definition[T]]) else None - } - case other => None - } - } - val (_, defList) = defs.foldLeft((Set.empty[DefType], List.empty[DefType])) { - case ((set, list), definition: Definition[T]) => - if (set.contains(definition)) (set, list) else (set + definition, definition +: list) - } - defList.reverse - } - - /** Selects all Definition's directly and indirectly instantiated within given root hierarchy, of provided type - * - * @note IMPORTANT: this function requires summoning a TypeTag[T], which will fail if T is an inner class, i.e. - * a class defined within another class. - * @note IMPORTANT: this function ignores type parameters. E.g. allDefinitionsOf[List[Int]] would return List[String]. - * - * @param root top of the hierarchy to search for definitions of given type - */ - def allDefinitionsOf[T <: BaseModule: TypeTag](root: Hierarchy[BaseModule]): Seq[Definition[T]] = { - type DefType = Definition[T] - val allDefSet = mutable.HashSet[Definition[BaseModule]]() - val defSet = mutable.HashSet[DefType]() - val defList = mutable.ArrayBuffer[DefType]() - def rec(hier: Definition[BaseModule]): Unit = { - if (hier.isA[T] && !defSet.contains(hier.asInstanceOf[DefType])) { - defSet += hier.asInstanceOf[DefType] - defList += hier.asInstanceOf[DefType] - } - allDefSet += hier - val allDefs = definitionsIn(hier) - allDefs.collect { - case d if !allDefSet.contains(d) => rec(d) - } - } - rec(root.toDefinition) - defList.toList - } - - /** Collects all components selected by collector within module and all children modules it instantiates - * directly or indirectly - * Accepts a collector function, rather than a collector partial function (see [[collectDeep]]) - * - * @note This API will not work with the new experimental hierarchy package. Instead, use allInstancesOf or allDefinitionsOf. - * - * @param module Module to collect components, as well as all children module it directly and indirectly instantiates - * @param collector Collector function to pick, given a module, which components to collect - * @param tag Required for generics to work, should ignore this - * @tparam T Type of the component that will be collected - */ - def getDeep[T](module: BaseModule)(collector: BaseModule => Seq[T]): Seq[T] = { - check(module) - val myItems = collector(module) - val deepChildrenItems = instances(module).flatMap { i => - getDeep(i)(collector) - } - myItems ++ deepChildrenItems - } - - /** Collects all components selected by collector within module and all children modules it instantiates - * directly or indirectly - * Accepts a collector partial function, rather than a collector function (see [[getDeep]]) - * - * @note This API will not work with the new experimental hierarchy package. Instead, use allInstancesOf or allDefinitionsOf. - * - * @param module Module to collect components, as well as all children module it directly and indirectly instantiates - * @param collector Collector partial function to pick, given a module, which components to collect - * @param tag Required for generics to work, should ignore this - * @tparam T Type of the component that will be collected - */ - def collectDeep[T](module: BaseModule)(collector: PartialFunction[BaseModule, T]): Iterable[T] = { - check(module) - val myItems = collector.lift(module) - val deepChildrenItems = instances(module).flatMap { i => - collectDeep(i)(collector) - } - myItems ++ deepChildrenItems - } - - /** Selects all modules directly instantiated within given module - * - * @note This API will not work with the new experimental hierarchy package. Instead, use instancesIn or definitionsIn. - * - * @param module - */ - def instances(module: BaseModule): Seq[BaseModule] = { - check(module) - module._component.get match { - case d: DefModule => - d.commands.flatMap { - case i: DefInstance => - i.id match { - case m: ModuleClone[_] if !m._madeFromDefinition => None - case _: PseudoModule => - throw new Exception( - "instances, collectDeep, and getDeep are currently incompatible with Definition/Instance!" - ) - case other => Some(other) - } - case _ => None - } - case other => Nil - } - } - - /** Selects all registers directly instantiated within given module - * @param module - */ - def registers(module: BaseModule): Seq[Data] = { - check(module) - module._component.get.asInstanceOf[DefModule].commands.collect { - case r: DefReg => r.id - case r: DefRegInit => r.id - } - } - - /** Selects all ios on a given module - * @param module - */ - def ios(module: BaseModule): Seq[Data] = { - check(module) - module._component.get.asInstanceOf[DefModule].ports.map(_.id) - } - - /** Selects all ios directly on a given Instance or Definition of a module - * @param parent the Definition or Instance to get the IOs of - */ - def ios[T <: BaseModule](parent: Hierarchy[T]): Seq[Data] = { - check(parent) - implicit val mg = new chisel3.internal.MacroGenerated {} - parent._lookup { x => ios(parent.proto) } - } - - /** Selects all SyncReadMems directly contained within given module - * @param module - */ - def syncReadMems(module: BaseModule): Seq[SyncReadMem[_]] = { - check(module) - module._component.get.asInstanceOf[DefModule].commands.collect { - case r: DefSeqMemory => r.id.asInstanceOf[SyncReadMem[_]] - } - } - - /** Selects all Mems directly contained within given module - * @param module - */ - def mems(module: BaseModule): Seq[Mem[_]] = { - check(module) - module._component.get.asInstanceOf[DefModule].commands.collect { - case r: DefMemory => r.id.asInstanceOf[Mem[_]] - } - } - - /** Selects all arithmetic or logical operators directly instantiated within given module - * @param module - */ - def ops(module: BaseModule): Seq[(String, Data)] = { - check(module) - module._component.get.asInstanceOf[DefModule].commands.collect { - case d: DefPrim[_] => (d.op.name, d.id) - } - } - - /** Selects a kind of arithmetic or logical operator directly instantiated within given module - * The kind of operators are contained in [[chisel3.internal.firrtl.PrimOp]] - * @param opKind the kind of operator, e.g. "mux", "add", or "bits" - * @param module - */ - def ops(opKind: String)(module: BaseModule): Seq[Data] = { - check(module) - module._component.get.asInstanceOf[DefModule].commands.collect { - case d: DefPrim[_] if d.op.name == opKind => d.id - } - } - - /** Selects all wires in a module - * @param module - */ - def wires(module: BaseModule): Seq[Data] = { - check(module) - module._component.get.asInstanceOf[DefModule].commands.collect { - case r: DefWire => r.id - } - } - - /** Selects all memory ports, including their direction and memory - * @param module - */ - def memPorts(module: BaseModule): Seq[(Data, MemPortDirection, MemBase[_])] = { - check(module) - module._component.get.asInstanceOf[DefModule].commands.collect { - case r: DefMemPort[_] => (r.id, r.dir, r.source.id.asInstanceOf[MemBase[_ <: Data]]) - } - } - - /** Selects all memory ports of a given direction, including their memory - * @param dir The direction of memory ports to select - * @param module - */ - def memPorts(dir: MemPortDirection)(module: BaseModule): Seq[(Data, MemBase[_])] = { - check(module) - module._component.get.asInstanceOf[DefModule].commands.collect { - case r: DefMemPort[_] if r.dir == dir => (r.id, r.source.id.asInstanceOf[MemBase[_ <: Data]]) - } - } - - /** Selects all components who have been set to be invalid, even if they are later connected to - * @param module - */ - def invalids(module: BaseModule): Seq[Data] = { - check(module) - module._component.get.asInstanceOf[DefModule].commands.collect { - case DefInvalid(_, arg) => getData(arg) - } - } - - /** Selects all components who are attached to a given signal, within a module - * @param module - */ - def attachedTo(module: BaseModule)(signal: Data): Set[Data] = { - check(module) - module._component.get - .asInstanceOf[DefModule] - .commands - .collect { - case Attach(_, seq) if seq.contains(signal) => seq - } - .flatMap { seq => seq.map(_.id.asInstanceOf[Data]) } - .toSet - } - - /** Selects all connections to a signal or its parent signal(s) (if the signal is an element of an aggregate signal) - * The when predicates surrounding each connection are included in the returned values - * - * E.g. if signal = io.foo.bar, connectionsTo will return all connections to io, io.foo, and io.bar - * @param module - * @param signal - */ - def connectionsTo(module: BaseModule)(signal: Data): Seq[PredicatedConnect] = { - check(module) - val sensitivitySignals = getIntermediateAndLeafs(signal).toSet - val predicatedConnects = mutable.ArrayBuffer[PredicatedConnect]() - val isPort = module._component.get - .asInstanceOf[DefModule] - .ports - .flatMap { p => getIntermediateAndLeafs(p.id) } - .contains(signal) - var prePredicates: Seq[Predicate] = Nil - var seenDef = isPort - searchWhens( - module, - (cmd: Command, preds) => { - cmd match { - case cmd: DefinitionIR if cmd.id.isInstanceOf[Data] => - val x = getIntermediateAndLeafs(cmd.id.asInstanceOf[Data]) - if (x.contains(signal)) prePredicates = preds - case Connect(_, loc @ Node(d: Data), exp) => - val effected = getEffected(loc).toSet - if (sensitivitySignals.intersect(effected).nonEmpty) { - val expData = getData(exp) - prePredicates.reverse - .zip(preds.reverse) - .foreach(x => assert(x._1 == x._2, s"Prepredicates $x must match for signal $signal")) - predicatedConnects += PredicatedConnect(preds.dropRight(prePredicates.size), d, expData, isBulk = false) - } - case BulkConnect(_, loc @ Node(d: Data), exp) => - val effected = getEffected(loc).toSet - if (sensitivitySignals.intersect(effected).nonEmpty) { - val expData = getData(exp) - prePredicates.reverse - .zip(preds.reverse) - .foreach(x => assert(x._1 == x._2, s"Prepredicates $x must match for signal $signal")) - predicatedConnects += PredicatedConnect(preds.dropRight(prePredicates.size), d, expData, isBulk = true) - } - case other => - } - } - ) - predicatedConnects.toSeq - } - - /** Selects all stop statements, and includes the predicates surrounding the stop statement - * - * @param module - */ - def stops(module: BaseModule): Seq[Stop] = { - val stops = mutable.ArrayBuffer[Stop]() - searchWhens( - module, - (cmd: Command, preds: Seq[Predicate]) => { - cmd match { - case chisel3.internal.firrtl.Stop(_, _, clock, ret) => - stops += Stop(preds, ret, getId(clock).asInstanceOf[Clock]) - case other => - } - } - ) - stops.toSeq - } - - /** Selects all printf statements, and includes the predicates surrounding the printf statement - * - * @param module - */ - def printfs(module: BaseModule): Seq[Printf] = { - val printfs = mutable.ArrayBuffer[Printf]() - searchWhens( - module, - (cmd: Command, preds: Seq[Predicate]) => { - cmd match { - case chisel3.internal.firrtl.Printf(id, _, clock, pable) => - printfs += Printf(id, preds, pable, getId(clock).asInstanceOf[Clock]) - case other => - } - } - ) - printfs.toSeq - } - - // Checks that a module has finished its construction - private def check(module: BaseModule): Unit = { - require(module.isClosed, "Can't use Selector on modules that have not finished construction!") - require(module._component.isDefined, "Can't use Selector on modules that don't have components!") - } - private def check(hierarchy: Hierarchy[BaseModule]): Unit = check(hierarchy.proto) - - // Given a loc, return all subcomponents of id that could be assigned to in connect - private def getEffected(a: Arg): Seq[Data] = a match { - case Node(id: Data) => getIntermediateAndLeafs(id) - case Slot(imm, name) => Seq(imm.id.asInstanceOf[Record].elements(name)) - case Index(imm, value) => getEffected(imm) - } - - // Given an arg, return the corresponding id. Don't use on a loc of a connect. - private def getId(a: Arg): HasId = a match { - case Node(id) => id - case l: ULit => l.num.U(l.w) - case l: SLit => l.num.S(l.w) - case l: FPLit => FixedPoint(l.num, l.w, l.binaryPoint) - case other => - sys.error(s"Something went horribly wrong! I was expecting ${other} to be a lit or a node!") - } - - private def getData(a: Arg): Data = a match { - case Node(data: Data) => data - case other => - sys.error(s"Something went horribly wrong! I was expecting ${other} to be Data!") - } - - // Given an id, either get its name or its value, if its a lit - private def getName(i: HasId): String = try { - i.toTarget match { - case r: ReferenceTarget => - val str = r.serialize - str.splitAt(str.indexOf('>'))._2.drop(1) - } - } catch { - case e: ChiselException => - i.getOptionRef.get match { - case l: LitArg => l.num.intValue.toString - } - } - - // Collects when predicates as it searches through a module, then applying processCommand to non-when related commands - private def searchWhens(module: BaseModule, processCommand: (Command, Seq[Predicate]) => Unit) = { - check(module) - module._component.get.asInstanceOf[DefModule].commands.foldLeft((Seq.empty[Predicate], Option.empty[Predicate])) { - (blah, cmd) => - (blah, cmd) match { - case ((preds, o), cmd) => - cmd match { - case WhenBegin(_, Node(pred: Bool)) => (When(pred) +: preds, None) - case WhenBegin(_, l: LitArg) if l.num == BigInt(1) => (When(true.B) +: preds, None) - case WhenBegin(_, l: LitArg) if l.num == BigInt(0) => (When(false.B) +: preds, None) - case other: WhenBegin => - sys.error(s"Something went horribly wrong! I was expecting ${other.pred} to be a lit or a bool!") - case _: WhenEnd => (preds.tail, Some(preds.head)) - case AltBegin(_) if o.isDefined => (o.get.not +: preds, o) - case _: AltBegin => - sys.error(s"Something went horribly wrong! I was expecting ${o} to be nonEmpty!") - case OtherwiseEnd(_, _) => (preds.tail, None) - case other => - processCommand(cmd, preds) - (preds, o) - } - } - } - } - - trait Serializeable { - def serialize: String - } - - /** Used to indicates a when's predicate (or its otherwise predicate) - */ - trait Predicate extends Serializeable { - val bool: Bool - def not: Predicate - } - - /** Used to represent [[chisel3.when]] predicate - * - * @param bool the when predicate - */ - case class When(bool: Bool) extends Predicate { - def not: WhenNot = WhenNot(bool) - def serialize: String = s"${getName(bool)}" - } - - /** Used to represent the `otherwise` predicate of a [[chisel3.when]] - * - * @param bool the when predicate corresponding to this otherwise predicate - */ - case class WhenNot(bool: Bool) extends Predicate { - def not: When = When(bool) - def serialize: String = s"!${getName(bool)}" - } - - /** Used to represent a connection or bulk connection - * - * Additionally contains the sequence of when predicates seen when the connection is declared - * - * @param preds - * @param loc - * @param exp - * @param isBulk - */ - case class PredicatedConnect(preds: Seq[Predicate], loc: Data, exp: Data, isBulk: Boolean) extends Serializeable { - def serialize: String = { - val moduleTarget = loc.toTarget.moduleTarget.serialize - s"$moduleTarget: when(${preds.map(_.serialize).mkString(" & ")}): ${getName(loc)} ${if (isBulk) "<>" else ":="} ${getName(exp)}" - } - } - - /** Used to represent a [[chisel3.stop]] - * - * @param preds - * @param ret - * @param clock - */ - case class Stop(preds: Seq[Predicate], ret: Int, clock: Clock) extends Serializeable { - def serialize: String = { - s"stop when(${preds.map(_.serialize).mkString(" & ")}) on ${getName(clock)}: $ret" - } - } - - /** Used to represent a [[chisel3.printf]] - * - * @param preds - * @param pable - * @param clock - */ - case class Printf(id: printf.Printf, preds: Seq[Predicate], pable: Printable, clock: Clock) extends Serializeable { - def serialize: String = { - s"printf when(${preds.map(_.serialize).mkString(" & ")}) on ${getName(clock)}: $pable" - } - } -} +// // SPDX-License-Identifier: Apache-2.0 + +// package chisel3.aop + +// import chisel3._ +// import chisel3.internal.{HasId} +// import chisel3.experimental.BaseModule +// import chisel3.experimental.FixedPoint +// import chisel3.internal.firrtl.{Definition => DefinitionIR, _} +// import chisel3.experimental.hierarchy._ +// import chisel3.internal.PseudoModule +// import chisel3.internal.BaseModule.ModuleClone +// import firrtl.annotations.ReferenceTarget +// import scala.reflect.runtime.universe.TypeTag + +// import scala.collection.mutable +// import chisel3.internal.naming.chiselName + +// /** Use to select Chisel components in a module, after that module has been constructed +// * Useful for adding additional Chisel annotations or for use within an [[Aspect]] +// */ +// object Select { + +// /** Return just leaf components of expanded node +// * +// * @param d Component to find leafs if aggregate typed. Intermediate fields/indicies are not included +// */ +// def getLeafs(d: Data): Seq[Data] = d match { +// case r: Record => r.elementsIterator.flatMap(getLeafs).toSeq +// case v: Vec[_] => v.getElements.flatMap(getLeafs) +// case other => Seq(other) +// } + +// /** Return all expanded components, including intermediate aggregate nodes +// * +// * @param d Component to find leafs if aggregate typed. Intermediate fields/indicies ARE included +// */ +// def getIntermediateAndLeafs(d: Data): Seq[Data] = d match { +// case r: Record => r +: r.elementsIterator.flatMap(getIntermediateAndLeafs).toSeq +// case v: Vec[_] => v +: v.getElements.flatMap(getIntermediateAndLeafs) +// case other => Seq(other) +// } + +// /** Selects all instances/modules directly instantiated within given definition +// * +// * @param parent +// */ +// def instancesIn(parent: Hierarchy[BaseModule]): Seq[Instance[BaseModule]] = { +// check(parent) +// implicit val mg = new chisel3.internal.MacroGenerated {} +// parent.proto._component.get match { +// case d: DefModule => +// d.commands.collect { +// case d: DefInstance => +// d.id match { +// case p: chisel3.internal.BaseModule.IsClone[_] => +// parent._lookup { x => new Instance(Clone(p)).asInstanceOf[Instance[BaseModule]] } +// case other: BaseModule => +// parent._lookup { x => other } +// } +// } +// case other => Nil +// } +// } + +// /** Selects all Instances of instances/modules directly instantiated within given module, of provided type +// * +// * @note IMPORTANT: this function requires summoning a TypeTag[T], which will fail if T is an inner class. +// * @note IMPORTANT: this function ignores type parameters. E.g. instancesOf[List[Int]] would return List[String]. +// * +// * @param parent hierarchy which instantiates the returned Definitions +// */ +// def instancesOf[T <: BaseModule: TypeTag](parent: Hierarchy[BaseModule]): Seq[Instance[T]] = { +// check(parent) +// implicit val mg = new chisel3.internal.MacroGenerated {} +// parent.proto._component.get match { +// case d: DefModule => +// d.commands.flatMap { +// case d: DefInstance => +// d.id match { +// case p: chisel3.internal.BaseModule.IsClone[_] => +// val i = parent._lookup { x => new Instance(Clone(p)).asInstanceOf[Instance[BaseModule]] } +// if (i.isA[T]) Some(i.asInstanceOf[Instance[T]]) else None +// case other: BaseModule => +// val i = parent._lookup { x => other } +// if (i.isA[T]) Some(i.asInstanceOf[Instance[T]]) else None +// } +// case other => None +// } +// case other => Nil +// } +// } + +// /** Selects all Instances directly and indirectly instantiated within given root hierarchy, of provided type +// * +// * @note IMPORTANT: this function requires summoning a TypeTag[T], which will fail if T is an inner class. +// * @note IMPORTANT: this function ignores type parameters. E.g. allInstancesOf[List[Int]] would return List[String]. +// * +// * @param root top of the hierarchy to search for instances/modules of given type +// */ +// def allInstancesOf[T <: BaseModule: TypeTag](root: Hierarchy[BaseModule]): Seq[Instance[T]] = { +// val soFar = if (root.isA[T]) Seq(root.toInstance.asInstanceOf[Instance[T]]) else Nil +// val allLocalInstances = instancesIn(root) +// soFar ++ (allLocalInstances.flatMap(allInstancesOf[T])) +// } + +// /** Selects the Definitions of all instances/modules directly instantiated within given module +// * +// * @param parent +// */ +// def definitionsIn(parent: Hierarchy[BaseModule]): Seq[Definition[BaseModule]] = { +// type DefType = Definition[BaseModule] +// implicit val mg = new chisel3.internal.MacroGenerated {} +// check(parent) +// val defs = parent.proto._component.get match { +// case d: DefModule => +// d.commands.collect { +// case i: DefInstance => +// i.id match { +// case p: chisel3.internal.BaseModule.IsClone[_] => +// parent._lookup { x => new Definition(Proto(p.getProto)).asInstanceOf[Definition[BaseModule]] } +// case other: BaseModule => +// parent._lookup { x => other.toDefinition } +// } +// } +// case other => Nil +// } +// val (_, defList) = defs.foldLeft((Set.empty[DefType], List.empty[DefType])) { +// case ((set, list), definition: Definition[BaseModule]) => +// if (set.contains(definition)) (set, list) else (set + definition, definition +: list) +// } +// defList.reverse +// } + +// /** Selects all Definitions of instances/modules directly instantiated within given module, of provided type +// * +// * @note IMPORTANT: this function requires summoning a TypeTag[T], which will fail if T is an inner class. +// * @note IMPORTANT: this function ignores type parameters. E.g. definitionsOf[List[Int]] would return List[String]. +// * +// * @param parent hierarchy which instantiates the returned Definitions +// */ +// def definitionsOf[T <: BaseModule: TypeTag](parent: Hierarchy[BaseModule]): Seq[Definition[T]] = { +// check(parent) +// implicit val mg = new chisel3.internal.MacroGenerated {} +// type DefType = Definition[T] +// val defs = parent.proto._component.get match { +// case d: DefModule => +// d.commands.flatMap { +// case d: DefInstance => +// d.id match { +// case p: chisel3.internal.BaseModule.IsClone[_] => +// val d = parent._lookup { x => new Definition(Clone(p)).asInstanceOf[Definition[BaseModule]] } +// if (d.isA[T]) Some(d.asInstanceOf[Definition[T]]) else None +// case other: BaseModule => +// val d = parent._lookup { x => other.toDefinition } +// if (d.isA[T]) Some(d.asInstanceOf[Definition[T]]) else None +// } +// case other => None +// } +// } +// val (_, defList) = defs.foldLeft((Set.empty[DefType], List.empty[DefType])) { +// case ((set, list), definition: Definition[T]) => +// if (set.contains(definition)) (set, list) else (set + definition, definition +: list) +// } +// defList.reverse +// } + +// /** Selects all Definition's directly and indirectly instantiated within given root hierarchy, of provided type +// * +// * @note IMPORTANT: this function requires summoning a TypeTag[T], which will fail if T is an inner class, i.e. +// * a class defined within another class. +// * @note IMPORTANT: this function ignores type parameters. E.g. allDefinitionsOf[List[Int]] would return List[String]. +// * +// * @param root top of the hierarchy to search for definitions of given type +// */ +// def allDefinitionsOf[T <: BaseModule: TypeTag](root: Hierarchy[BaseModule]): Seq[Definition[T]] = { +// type DefType = Definition[T] +// val allDefSet = mutable.HashSet[Definition[BaseModule]]() +// val defSet = mutable.HashSet[DefType]() +// val defList = mutable.ArrayBuffer[DefType]() +// def rec(hier: Definition[BaseModule]): Unit = { +// if (hier.isA[T] && !defSet.contains(hier.asInstanceOf[DefType])) { +// defSet += hier.asInstanceOf[DefType] +// defList += hier.asInstanceOf[DefType] +// } +// allDefSet += hier +// val allDefs = definitionsIn(hier) +// allDefs.collect { +// case d if !allDefSet.contains(d) => rec(d) +// } +// } +// rec(root.toDefinition) +// defList.toList +// } + +// /** Collects all components selected by collector within module and all children modules it instantiates +// * directly or indirectly +// * Accepts a collector function, rather than a collector partial function (see [[collectDeep]]) +// * +// * @note This API will not work with the new experimental hierarchy package. Instead, use allInstancesOf or allDefinitionsOf. +// * +// * @param module Module to collect components, as well as all children module it directly and indirectly instantiates +// * @param collector Collector function to pick, given a module, which components to collect +// * @param tag Required for generics to work, should ignore this +// * @tparam T Type of the component that will be collected +// */ +// def getDeep[T](module: BaseModule)(collector: BaseModule => Seq[T]): Seq[T] = { +// check(module) +// val myItems = collector(module) +// val deepChildrenItems = instances(module).flatMap { i => +// getDeep(i)(collector) +// } +// myItems ++ deepChildrenItems +// } + +// /** Collects all components selected by collector within module and all children modules it instantiates +// * directly or indirectly +// * Accepts a collector partial function, rather than a collector function (see [[getDeep]]) +// * +// * @note This API will not work with the new experimental hierarchy package. Instead, use allInstancesOf or allDefinitionsOf. +// * +// * @param module Module to collect components, as well as all children module it directly and indirectly instantiates +// * @param collector Collector partial function to pick, given a module, which components to collect +// * @param tag Required for generics to work, should ignore this +// * @tparam T Type of the component that will be collected +// */ +// def collectDeep[T](module: BaseModule)(collector: PartialFunction[BaseModule, T]): Iterable[T] = { +// check(module) +// val myItems = collector.lift(module) +// val deepChildrenItems = instances(module).flatMap { i => +// collectDeep(i)(collector) +// } +// myItems ++ deepChildrenItems +// } + +// /** Selects all modules directly instantiated within given module +// * +// * @note This API will not work with the new experimental hierarchy package. Instead, use instancesIn or definitionsIn. +// * +// * @param module +// */ +// def instances(module: BaseModule): Seq[BaseModule] = { +// check(module) +// module._component.get match { +// case d: DefModule => +// d.commands.flatMap { +// case i: DefInstance => +// i.id match { +// case m: ModuleClone[_] if !m._madeFromDefinition => None +// case _: PseudoModule => +// throw new Exception( +// "instances, collectDeep, and getDeep are currently incompatible with Definition/Instance!" +// ) +// case other => Some(other) +// } +// case _ => None +// } +// case other => Nil +// } +// } + +// /** Selects all registers directly instantiated within given module +// * @param module +// */ +// def registers(module: BaseModule): Seq[Data] = { +// check(module) +// module._component.get.asInstanceOf[DefModule].commands.collect { +// case r: DefReg => r.id +// case r: DefRegInit => r.id +// } +// } + +// /** Selects all ios on a given module +// * @param module +// */ +// def ios(module: BaseModule): Seq[Data] = { +// check(module) +// module._component.get.asInstanceOf[DefModule].ports.map(_.id) +// } + +// /** Selects all ios directly on a given Instance or Definition of a module +// * @param parent the Definition or Instance to get the IOs of +// */ +// def ios[T <: BaseModule](parent: Hierarchy[T]): Seq[Data] = { +// check(parent) +// implicit val mg = new chisel3.internal.MacroGenerated {} +// parent._lookup { x => ios(parent.proto) } +// } + +// /** Selects all SyncReadMems directly contained within given module +// * @param module +// */ +// def syncReadMems(module: BaseModule): Seq[SyncReadMem[_]] = { +// check(module) +// module._component.get.asInstanceOf[DefModule].commands.collect { +// case r: DefSeqMemory => r.id.asInstanceOf[SyncReadMem[_]] +// } +// } + +// /** Selects all Mems directly contained within given module +// * @param module +// */ +// def mems(module: BaseModule): Seq[Mem[_]] = { +// check(module) +// module._component.get.asInstanceOf[DefModule].commands.collect { +// case r: DefMemory => r.id.asInstanceOf[Mem[_]] +// } +// } + +// /** Selects all arithmetic or logical operators directly instantiated within given module +// * @param module +// */ +// def ops(module: BaseModule): Seq[(String, Data)] = { +// check(module) +// module._component.get.asInstanceOf[DefModule].commands.collect { +// case d: DefPrim[_] => (d.op.name, d.id) +// } +// } + +// /** Selects a kind of arithmetic or logical operator directly instantiated within given module +// * The kind of operators are contained in [[chisel3.internal.firrtl.PrimOp]] +// * @param opKind the kind of operator, e.g. "mux", "add", or "bits" +// * @param module +// */ +// def ops(opKind: String)(module: BaseModule): Seq[Data] = { +// check(module) +// module._component.get.asInstanceOf[DefModule].commands.collect { +// case d: DefPrim[_] if d.op.name == opKind => d.id +// } +// } + +// /** Selects all wires in a module +// * @param module +// */ +// def wires(module: BaseModule): Seq[Data] = { +// check(module) +// module._component.get.asInstanceOf[DefModule].commands.collect { +// case r: DefWire => r.id +// } +// } + +// /** Selects all memory ports, including their direction and memory +// * @param module +// */ +// def memPorts(module: BaseModule): Seq[(Data, MemPortDirection, MemBase[_])] = { +// check(module) +// module._component.get.asInstanceOf[DefModule].commands.collect { +// case r: DefMemPort[_] => (r.id, r.dir, r.source.id.asInstanceOf[MemBase[_ <: Data]]) +// } +// } + +// /** Selects all memory ports of a given direction, including their memory +// * @param dir The direction of memory ports to select +// * @param module +// */ +// def memPorts(dir: MemPortDirection)(module: BaseModule): Seq[(Data, MemBase[_])] = { +// check(module) +// module._component.get.asInstanceOf[DefModule].commands.collect { +// case r: DefMemPort[_] if r.dir == dir => (r.id, r.source.id.asInstanceOf[MemBase[_ <: Data]]) +// } +// } + +// /** Selects all components who have been set to be invalid, even if they are later connected to +// * @param module +// */ +// def invalids(module: BaseModule): Seq[Data] = { +// check(module) +// module._component.get.asInstanceOf[DefModule].commands.collect { +// case DefInvalid(_, arg) => getData(arg) +// } +// } + +// /** Selects all components who are attached to a given signal, within a module +// * @param module +// */ +// def attachedTo(module: BaseModule)(signal: Data): Set[Data] = { +// check(module) +// module._component.get +// .asInstanceOf[DefModule] +// .commands +// .collect { +// case Attach(_, seq) if seq.contains(signal) => seq +// } +// .flatMap { seq => seq.map(_.id.asInstanceOf[Data]) } +// .toSet +// } + +// /** Selects all connections to a signal or its parent signal(s) (if the signal is an element of an aggregate signal) +// * The when predicates surrounding each connection are included in the returned values +// * +// * E.g. if signal = io.foo.bar, connectionsTo will return all connections to io, io.foo, and io.bar +// * @param module +// * @param signal +// */ +// def connectionsTo(module: BaseModule)(signal: Data): Seq[PredicatedConnect] = { +// check(module) +// val sensitivitySignals = getIntermediateAndLeafs(signal).toSet +// val predicatedConnects = mutable.ArrayBuffer[PredicatedConnect]() +// val isPort = module._component.get +// .asInstanceOf[DefModule] +// .ports +// .flatMap { p => getIntermediateAndLeafs(p.id) } +// .contains(signal) +// var prePredicates: Seq[Predicate] = Nil +// var seenDef = isPort +// searchWhens( +// module, +// (cmd: Command, preds) => { +// cmd match { +// case cmd: DefinitionIR if cmd.id.isInstanceOf[Data] => +// val x = getIntermediateAndLeafs(cmd.id.asInstanceOf[Data]) +// if (x.contains(signal)) prePredicates = preds +// case Connect(_, loc @ Node(d: Data), exp) => +// val effected = getEffected(loc).toSet +// if (sensitivitySignals.intersect(effected).nonEmpty) { +// val expData = getData(exp) +// prePredicates.reverse +// .zip(preds.reverse) +// .foreach(x => assert(x._1 == x._2, s"Prepredicates $x must match for signal $signal")) +// predicatedConnects += PredicatedConnect(preds.dropRight(prePredicates.size), d, expData, isBulk = false) +// } +// case BulkConnect(_, loc @ Node(d: Data), exp) => +// val effected = getEffected(loc).toSet +// if (sensitivitySignals.intersect(effected).nonEmpty) { +// val expData = getData(exp) +// prePredicates.reverse +// .zip(preds.reverse) +// .foreach(x => assert(x._1 == x._2, s"Prepredicates $x must match for signal $signal")) +// predicatedConnects += PredicatedConnect(preds.dropRight(prePredicates.size), d, expData, isBulk = true) +// } +// case other => +// } +// } +// ) +// predicatedConnects.toSeq +// } + +// /** Selects all stop statements, and includes the predicates surrounding the stop statement +// * +// * @param module +// */ +// def stops(module: BaseModule): Seq[Stop] = { +// val stops = mutable.ArrayBuffer[Stop]() +// searchWhens( +// module, +// (cmd: Command, preds: Seq[Predicate]) => { +// cmd match { +// case chisel3.internal.firrtl.Stop(_, _, clock, ret) => +// stops += Stop(preds, ret, getId(clock).asInstanceOf[Clock]) +// case other => +// } +// } +// ) +// stops.toSeq +// } + +// /** Selects all printf statements, and includes the predicates surrounding the printf statement +// * +// * @param module +// */ +// def printfs(module: BaseModule): Seq[Printf] = { +// val printfs = mutable.ArrayBuffer[Printf]() +// searchWhens( +// module, +// (cmd: Command, preds: Seq[Predicate]) => { +// cmd match { +// case chisel3.internal.firrtl.Printf(id, _, clock, pable) => +// printfs += Printf(id, preds, pable, getId(clock).asInstanceOf[Clock]) +// case other => +// } +// } +// ) +// printfs.toSeq +// } + +// // Checks that a module has finished its construction +// private def check(module: BaseModule): Unit = { +// require(module.isClosed, "Can't use Selector on modules that have not finished construction!") +// require(module._component.isDefined, "Can't use Selector on modules that don't have components!") +// } +// private def check(hierarchy: Hierarchy[BaseModule]): Unit = check(hierarchy.proto) + +// // Given a loc, return all subcomponents of id that could be assigned to in connect +// private def getEffected(a: Arg): Seq[Data] = a match { +// case Node(id: Data) => getIntermediateAndLeafs(id) +// case Slot(imm, name) => Seq(imm.id.asInstanceOf[Record].elements(name)) +// case Index(imm, value) => getEffected(imm) +// } + +// // Given an arg, return the corresponding id. Don't use on a loc of a connect. +// private def getId(a: Arg): HasId = a match { +// case Node(id) => id +// case l: ULit => l.num.U(l.w) +// case l: SLit => l.num.S(l.w) +// case l: FPLit => FixedPoint(l.num, l.w, l.binaryPoint) +// case other => +// sys.error(s"Something went horribly wrong! I was expecting ${other} to be a lit or a node!") +// } + +// private def getData(a: Arg): Data = a match { +// case Node(data: Data) => data +// case other => +// sys.error(s"Something went horribly wrong! I was expecting ${other} to be Data!") +// } + +// // Given an id, either get its name or its value, if its a lit +// private def getName(i: HasId): String = try { +// i.toTarget match { +// case r: ReferenceTarget => +// val str = r.serialize +// str.splitAt(str.indexOf('>'))._2.drop(1) +// } +// } catch { +// case e: ChiselException => +// i.getOptionRef.get match { +// case l: LitArg => l.num.intValue.toString +// } +// } + +// // Collects when predicates as it searches through a module, then applying processCommand to non-when related commands +// private def searchWhens(module: BaseModule, processCommand: (Command, Seq[Predicate]) => Unit) = { +// check(module) +// module._component.get.asInstanceOf[DefModule].commands.foldLeft((Seq.empty[Predicate], Option.empty[Predicate])) { +// (blah, cmd) => +// (blah, cmd) match { +// case ((preds, o), cmd) => +// cmd match { +// case WhenBegin(_, Node(pred: Bool)) => (When(pred) +: preds, None) +// case WhenBegin(_, l: LitArg) if l.num == BigInt(1) => (When(true.B) +: preds, None) +// case WhenBegin(_, l: LitArg) if l.num == BigInt(0) => (When(false.B) +: preds, None) +// case other: WhenBegin => +// sys.error(s"Something went horribly wrong! I was expecting ${other.pred} to be a lit or a bool!") +// case _: WhenEnd => (preds.tail, Some(preds.head)) +// case AltBegin(_) if o.isDefined => (o.get.not +: preds, o) +// case _: AltBegin => +// sys.error(s"Something went horribly wrong! I was expecting ${o} to be nonEmpty!") +// case OtherwiseEnd(_, _) => (preds.tail, None) +// case other => +// processCommand(cmd, preds) +// (preds, o) +// } +// } +// } +// } + +// trait Serializeable { +// def serialize: String +// } + +// /** Used to indicates a when's predicate (or its otherwise predicate) +// */ +// trait Predicate extends Serializeable { +// val bool: Bool +// def not: Predicate +// } + +// /** Used to represent [[chisel3.when]] predicate +// * +// * @param bool the when predicate +// */ +// case class When(bool: Bool) extends Predicate { +// def not: WhenNot = WhenNot(bool) +// def serialize: String = s"${getName(bool)}" +// } + +// /** Used to represent the `otherwise` predicate of a [[chisel3.when]] +// * +// * @param bool the when predicate corresponding to this otherwise predicate +// */ +// case class WhenNot(bool: Bool) extends Predicate { +// def not: When = When(bool) +// def serialize: String = s"!${getName(bool)}" +// } + +// /** Used to represent a connection or bulk connection +// * +// * Additionally contains the sequence of when predicates seen when the connection is declared +// * +// * @param preds +// * @param loc +// * @param exp +// * @param isBulk +// */ +// case class PredicatedConnect(preds: Seq[Predicate], loc: Data, exp: Data, isBulk: Boolean) extends Serializeable { +// def serialize: String = { +// val moduleTarget = loc.toTarget.moduleTarget.serialize +// s"$moduleTarget: when(${preds.map(_.serialize).mkString(" & ")}): ${getName(loc)} ${if (isBulk) "<>" else ":="} ${getName(exp)}" +// } +// } + +// /** Used to represent a [[chisel3.stop]] +// * +// * @param preds +// * @param ret +// * @param clock +// */ +// case class Stop(preds: Seq[Predicate], ret: Int, clock: Clock) extends Serializeable { +// def serialize: String = { +// s"stop when(${preds.map(_.serialize).mkString(" & ")}) on ${getName(clock)}: $ret" +// } +// } + +// /** Used to represent a [[chisel3.printf]] +// * +// * @param preds +// * @param pable +// * @param clock +// */ +// case class Printf(id: printf.Printf, preds: Seq[Predicate], pable: Printable, clock: Clock) extends Serializeable { +// def serialize: String = { +// s"printf when(${preds.map(_.serialize).mkString(" & ")}) on ${getName(clock)}: $pable" +// } +// } +// } diff --git a/src/main/scala/chisel3/aop/injecting/InjectStatement.scala b/src/main/scala/chisel3/aop/injecting/InjectStatement.scala index dbe1fd7b..be12cf32 100644 --- a/src/main/scala/chisel3/aop/injecting/InjectStatement.scala +++ b/src/main/scala/chisel3/aop/injecting/InjectStatement.scala @@ -1,26 +1,26 @@ -// SPDX-License-Identifier: Apache-2.0 +// // SPDX-License-Identifier: Apache-2.0 -package chisel3.aop.injecting +// package chisel3.aop.injecting -import chisel3.stage.phases.AspectPhase -import firrtl.annotations.{Annotation, ModuleTarget, NoTargetAnnotation, SingleTargetAnnotation} +// import chisel3.stage.phases.AspectPhase +// import firrtl.annotations.{Annotation, ModuleTarget, NoTargetAnnotation, SingleTargetAnnotation} -/** Contains all information needed to inject statements into a module - * - * Generated when a [[InjectingAspect]] is consumed by a [[AspectPhase]] - * Consumed by [[InjectingTransform]] - * - * @param module Module to inject code into at the end of the module - * @param s Statements to inject - * @param modules Additional modules that may be instantiated by s - * @param annotations Additional annotations that should be passed down compiler - */ -case class InjectStatement( - module: ModuleTarget, - s: firrtl.ir.Statement, - modules: Seq[firrtl.ir.DefModule], - annotations: Seq[Annotation]) - extends SingleTargetAnnotation[ModuleTarget] { - val target: ModuleTarget = module - override def duplicate(n: ModuleTarget): Annotation = this.copy(module = n) -} +// /** Contains all information needed to inject statements into a module +// * +// * Generated when a [[InjectingAspect]] is consumed by a [[AspectPhase]] +// * Consumed by [[InjectingTransform]] +// * +// * @param module Module to inject code into at the end of the module +// * @param s Statements to inject +// * @param modules Additional modules that may be instantiated by s +// * @param annotations Additional annotations that should be passed down compiler +// */ +// case class InjectStatement( +// module: ModuleTarget, +// s: firrtl.ir.Statement, +// modules: Seq[firrtl.ir.DefModule], +// annotations: Seq[Annotation]) +// extends SingleTargetAnnotation[ModuleTarget] { +// val target: ModuleTarget = module +// override def duplicate(n: ModuleTarget): Annotation = this.copy(module = n) +// } diff --git a/src/main/scala/chisel3/aop/injecting/InjectingAspect.scala b/src/main/scala/chisel3/aop/injecting/InjectingAspect.scala index ecce19e1..8682785b 100644 --- a/src/main/scala/chisel3/aop/injecting/InjectingAspect.scala +++ b/src/main/scala/chisel3/aop/injecting/InjectingAspect.scala @@ -1,108 +1,108 @@ -// SPDX-License-Identifier: Apache-2.0 +// // SPDX-License-Identifier: Apache-2.0 -package chisel3.aop.injecting +// package chisel3.aop.injecting -import chisel3.{withClockAndReset, Module, ModuleAspect, RawModule} -import chisel3.aop._ -import chisel3.internal.{Builder, DynamicContext} -import chisel3.internal.firrtl.DefModule -import chisel3.stage.{ChiselOptions, DesignAnnotation} -import firrtl.annotations.ModuleTarget -import firrtl.stage.RunFirrtlTransformAnnotation -import firrtl.options.Viewer.view -import firrtl.{ir, _} +// import chisel3.{withClockAndReset, Module, ModuleAspect, RawModule} +// import chisel3.aop._ +// import chisel3.internal.{Builder, DynamicContext} +// import chisel3.internal.firrtl.DefModule +// import chisel3.stage.{ChiselOptions, DesignAnnotation} +// import firrtl.annotations.ModuleTarget +// import firrtl.stage.RunFirrtlTransformAnnotation +// import firrtl.options.Viewer.view +// import firrtl.{ir, _} -import scala.collection.mutable +// import scala.collection.mutable -/** Aspect to inject Chisel code into a module of type M - * - * @param selectRoots Given top-level module, pick the instances of a module to apply the aspect (root module) - * @param injection Function to generate Chisel hardware that will be injected to the end of module m - * Signals in m can be referenced and assigned to as if inside m (yes, it is a bit magical) - * @tparam T Type of top-level module - * @tparam M Type of root module (join point) - */ -case class InjectingAspect[T <: RawModule, M <: RawModule]( - selectRoots: T => Iterable[M], - injection: M => Unit) - extends InjectorAspect[T, M]( - selectRoots, - injection - ) +// /** Aspect to inject Chisel code into a module of type M +// * +// * @param selectRoots Given top-level module, pick the instances of a module to apply the aspect (root module) +// * @param injection Function to generate Chisel hardware that will be injected to the end of module m +// * Signals in m can be referenced and assigned to as if inside m (yes, it is a bit magical) +// * @tparam T Type of top-level module +// * @tparam M Type of root module (join point) +// */ +// case class InjectingAspect[T <: RawModule, M <: RawModule]( +// selectRoots: T => Iterable[M], +// injection: M => Unit) +// extends InjectorAspect[T, M]( +// selectRoots, +// injection +// ) -/** Extend to inject Chisel code into a module of type M - * - * @param selectRoots Given top-level module, pick the instances of a module to apply the aspect (root module) - * @param injection Function to generate Chisel hardware that will be injected to the end of module m - * Signals in m can be referenced and assigned to as if inside m (yes, it is a bit magical) - * @tparam T Type of top-level module - * @tparam M Type of root module (join point) - */ -abstract class InjectorAspect[T <: RawModule, M <: RawModule]( - selectRoots: T => Iterable[M], - injection: M => Unit) - extends Aspect[T] { - final def toAnnotation(top: T): AnnotationSeq = { - val moduleNames = - Select.allDefinitionsOf[chisel3.experimental.BaseModule](top.toDefinition).map { i => i.toTarget.module }.toSeq - toAnnotation(selectRoots(top), top.name, moduleNames) - } +// /** Extend to inject Chisel code into a module of type M +// * +// * @param selectRoots Given top-level module, pick the instances of a module to apply the aspect (root module) +// * @param injection Function to generate Chisel hardware that will be injected to the end of module m +// * Signals in m can be referenced and assigned to as if inside m (yes, it is a bit magical) +// * @tparam T Type of top-level module +// * @tparam M Type of root module (join point) +// */ +// abstract class InjectorAspect[T <: RawModule, M <: RawModule]( +// selectRoots: T => Iterable[M], +// injection: M => Unit) +// extends Aspect[T] { +// final def toAnnotation(top: T): AnnotationSeq = { +// val moduleNames = +// Select.allDefinitionsOf[chisel3.experimental.BaseModule](top.toDefinition).map { i => i.toTarget.module }.toSeq +// toAnnotation(selectRoots(top), top.name, moduleNames) +// } - /** Returns annotations which contain all injection logic - * - * @param modules The modules to inject into - * @param circuit Top level circuit - * @param moduleNames The names of all existing modules in the original circuit, to avoid name collisions - * @return - */ - final def toAnnotation(modules: Iterable[M], circuit: String, moduleNames: Seq[String]): AnnotationSeq = { - RunFirrtlTransformAnnotation(new InjectingTransform) +: modules.map { module => - val chiselOptions = view[ChiselOptions](annotationsInAspect) - val dynamicContext = - new DynamicContext( - annotationsInAspect, - chiselOptions.throwOnFirstError, - chiselOptions.warnReflectiveNaming, - chiselOptions.warningsAsErrors - ) - // Add existing module names into the namespace. If injection logic instantiates new modules - // which would share the same name, they will get uniquified accordingly - moduleNames.foreach { n => - dynamicContext.globalNamespace.name(n) - } +// /** Returns annotations which contain all injection logic +// * +// * @param modules The modules to inject into +// * @param circuit Top level circuit +// * @param moduleNames The names of all existing modules in the original circuit, to avoid name collisions +// * @return +// */ +// final def toAnnotation(modules: Iterable[M], circuit: String, moduleNames: Seq[String]): AnnotationSeq = { +// RunFirrtlTransformAnnotation(new InjectingTransform) +: modules.map { module => +// val chiselOptions = view[ChiselOptions](annotationsInAspect) +// val dynamicContext = +// new DynamicContext( +// annotationsInAspect, +// chiselOptions.throwOnFirstError, +// chiselOptions.warnReflectiveNaming, +// chiselOptions.warningsAsErrors +// ) +// // Add existing module names into the namespace. If injection logic instantiates new modules +// // which would share the same name, they will get uniquified accordingly +// moduleNames.foreach { n => +// dynamicContext.globalNamespace.name(n) +// } - val (chiselIR, _) = Builder.build( - Module(new ModuleAspect(module) { - module match { - case x: Module => withClockAndReset(x.clock, x.reset) { injection(module) } - case x: RawModule => injection(module) - } - }), - dynamicContext - ) +// val (chiselIR, _) = Builder.build( +// Module(new ModuleAspect(module) { +// module match { +// case x: Module => withClockAndReset(x.clock, x.reset) { injection(module) } +// case x: RawModule => injection(module) +// } +// }), +// dynamicContext +// ) - val comps = chiselIR.components.map { - case x: DefModule if x.name == module.name => x.copy(id = module) - case other => other - } +// val comps = chiselIR.components.map { +// case x: DefModule if x.name == module.name => x.copy(id = module) +// case other => other +// } - val annotations = chiselIR.annotations.map(_.toFirrtl).filterNot { a => a.isInstanceOf[DesignAnnotation[_]] } +// val annotations = chiselIR.annotations.map(_.toFirrtl).filterNot { a => a.isInstanceOf[DesignAnnotation[_]] } - /** Statements to be injected via aspect. */ - val stmts = mutable.ArrayBuffer[ir.Statement]() +// /** Statements to be injected via aspect. */ +// val stmts = mutable.ArrayBuffer[ir.Statement]() - /** Modules to be injected via aspect. */ - val modules = Aspect.getFirrtl(chiselIR.copy(components = comps)).modules.flatMap { - // for "container" modules, inject their statements - case m: firrtl.ir.Module if m.name == module.name => - stmts += m.body - Nil - // for modules to be injected - case other: firrtl.ir.DefModule => - Seq(other) - } +// /** Modules to be injected via aspect. */ +// val modules = Aspect.getFirrtl(chiselIR.copy(components = comps)).modules.flatMap { +// // for "container" modules, inject their statements +// case m: firrtl.ir.Module if m.name == module.name => +// stmts += m.body +// Nil +// // for modules to be injected +// case other: firrtl.ir.DefModule => +// Seq(other) +// } - InjectStatement(ModuleTarget(circuit, module.name), ir.Block(stmts.toSeq), modules, annotations) - }.toSeq - } -} +// InjectStatement(ModuleTarget(circuit, module.name), ir.Block(stmts.toSeq), modules, annotations) +// }.toSeq +// } +// } diff --git a/src/main/scala/chisel3/aop/injecting/InjectingTransform.scala b/src/main/scala/chisel3/aop/injecting/InjectingTransform.scala index 8a0b6ecb..a7d47243 100644 --- a/src/main/scala/chisel3/aop/injecting/InjectingTransform.scala +++ b/src/main/scala/chisel3/aop/injecting/InjectingTransform.scala @@ -1,46 +1,46 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chisel3.aop.injecting - -import firrtl.{ir, ChirrtlForm, CircuitForm, CircuitState, Transform} - -import scala.collection.mutable - -/** Appends statements contained in [[InjectStatement]] annotations to the end of their corresponding modules - * - * Implemented with Chisel Aspects and the [[chisel3.aop.injecting]] library - */ -class InjectingTransform extends Transform { - override def inputForm: CircuitForm = ChirrtlForm - override def outputForm: CircuitForm = ChirrtlForm - - override def execute(state: CircuitState): CircuitState = { - - val addStmtMap = mutable.HashMap[String, Seq[ir.Statement]]() - val addModules = mutable.ArrayBuffer[ir.DefModule]() - - // Populate addStmtMap and addModules, return annotations in InjectStatements, and omit InjectStatement annotation - val newAnnotations = state.annotations.flatMap { - case InjectStatement(mt, s, addedModules, annotations) => - addModules ++= addedModules - addStmtMap(mt.module) = s +: addStmtMap.getOrElse(mt.module, Nil) - annotations - case other => Seq(other) - } - - // Append all statements to end of corresponding modules - val newModules = state.circuit.modules.map { m: ir.DefModule => - m match { - case m: ir.Module if addStmtMap.contains(m.name) => - m.copy(body = ir.Block(m.body +: addStmtMap(m.name))) - case m: _root_.firrtl.ir.ExtModule if addStmtMap.contains(m.name) => - ir.Module(m.info, m.name, m.ports, ir.Block(addStmtMap(m.name))) - case other: ir.DefModule => other - } - } - - // Return updated circuit and annotations - val newCircuit = state.circuit.copy(modules = newModules ++ addModules) - state.copy(annotations = newAnnotations, circuit = newCircuit) - } -} +// // SPDX-License-Identifier: Apache-2.0 + +// package chisel3.aop.injecting + +// import firrtl.{ir, ChirrtlForm, CircuitForm, CircuitState, Transform} + +// import scala.collection.mutable + +// /** Appends statements contained in [[InjectStatement]] annotations to the end of their corresponding modules +// * +// * Implemented with Chisel Aspects and the [[chisel3.aop.injecting]] library +// */ +// class InjectingTransform extends Transform { +// override def inputForm: CircuitForm = ChirrtlForm +// override def outputForm: CircuitForm = ChirrtlForm + +// override def execute(state: CircuitState): CircuitState = { + +// val addStmtMap = mutable.HashMap[String, Seq[ir.Statement]]() +// val addModules = mutable.ArrayBuffer[ir.DefModule]() + +// // Populate addStmtMap and addModules, return annotations in InjectStatements, and omit InjectStatement annotation +// val newAnnotations = state.annotations.flatMap { +// case InjectStatement(mt, s, addedModules, annotations) => +// addModules ++= addedModules +// addStmtMap(mt.module) = s +: addStmtMap.getOrElse(mt.module, Nil) +// annotations +// case other => Seq(other) +// } + +// // Append all statements to end of corresponding modules +// val newModules = state.circuit.modules.map { m: ir.DefModule => +// m match { +// case m: ir.Module if addStmtMap.contains(m.name) => +// m.copy(body = ir.Block(m.body +: addStmtMap(m.name))) +// case m: _root_.firrtl.ir.ExtModule if addStmtMap.contains(m.name) => +// ir.Module(m.info, m.name, m.ports, ir.Block(addStmtMap(m.name))) +// case other: ir.DefModule => other +// } +// } + +// // Return updated circuit and annotations +// val newCircuit = state.circuit.copy(modules = newModules ++ addModules) +// state.copy(annotations = newAnnotations, circuit = newCircuit) +// } +// } diff --git a/src/main/scala/chisel3/aop/inspecting/InspectingAspect.scala b/src/main/scala/chisel3/aop/inspecting/InspectingAspect.scala index 1340f253..9c9dc987 100644 --- a/src/main/scala/chisel3/aop/inspecting/InspectingAspect.scala +++ b/src/main/scala/chisel3/aop/inspecting/InspectingAspect.scala @@ -1,26 +1,26 @@ -// SPDX-License-Identifier: Apache-2.0 +// // SPDX-License-Identifier: Apache-2.0 -package chisel3.aop.inspecting +// package chisel3.aop.inspecting -import chisel3.RawModule -import chisel3.aop.Aspect -import firrtl.AnnotationSeq +// import chisel3.RawModule +// import chisel3.aop.Aspect +// import firrtl.AnnotationSeq -/** Use for inspecting an elaborated design and printing out results - * - * @param inspect Given top-level design, print things and return nothing - * @tparam T Type of top-level module - */ -case class InspectingAspect[T <: RawModule](inspect: T => Unit) extends InspectorAspect[T](inspect) +// /** Use for inspecting an elaborated design and printing out results +// * +// * @param inspect Given top-level design, print things and return nothing +// * @tparam T Type of top-level module +// */ +// case class InspectingAspect[T <: RawModule](inspect: T => Unit) extends InspectorAspect[T](inspect) -/** Extend to make custom inspections of an elaborated design and printing out results - * - * @param inspect Given top-level design, print things and return nothing - * @tparam T Type of top-level module - */ -abstract class InspectorAspect[T <: RawModule](inspect: T => Unit) extends Aspect[T] { - override def toAnnotation(top: T): AnnotationSeq = { - inspect(top) - Nil - } -} +// /** Extend to make custom inspections of an elaborated design and printing out results +// * +// * @param inspect Given top-level design, print things and return nothing +// * @tparam T Type of top-level module +// */ +// abstract class InspectorAspect[T <: RawModule](inspect: T => Unit) extends Aspect[T] { +// override def toAnnotation(top: T): AnnotationSeq = { +// inspect(top) +// Nil +// } +// } diff --git a/src/main/scala/chisel3/stage/ChiselPhase.scala b/src/main/scala/chisel3/stage/ChiselPhase.scala index 6c7affbc..fe6ab29a 100644 --- a/src/main/scala/chisel3/stage/ChiselPhase.scala +++ b/src/main/scala/chisel3/stage/ChiselPhase.scala @@ -18,7 +18,7 @@ private[chisel3] object ChiselPhase { Dependency[chisel3.stage.phases.Checks], Dependency[chisel3.stage.phases.AddImplicitOutputFile], Dependency[chisel3.stage.phases.AddImplicitOutputAnnotationFile], - Dependency[chisel3.stage.phases.MaybeAspectPhase], + // Dependency[chisel3.stage.phases.MaybeAspectPhase], Dependency[chisel3.stage.phases.AddSerializationAnnotations], Dependency[chisel3.stage.phases.Convert], Dependency[chisel3.stage.phases.MaybeFirrtlStage] diff --git a/src/main/scala/chisel3/stage/ChiselStage.scala b/src/main/scala/chisel3/stage/ChiselStage.scala index 1224a8f1..dd9a3ae7 100644 --- a/src/main/scala/chisel3/stage/ChiselStage.scala +++ b/src/main/scala/chisel3/stage/ChiselStage.scala @@ -158,7 +158,7 @@ object ChiselStage { Dependency[chisel3.stage.phases.Elaborate], Dependency[chisel3.stage.phases.AddImplicitOutputFile], Dependency[chisel3.stage.phases.AddImplicitOutputAnnotationFile], - Dependency[chisel3.stage.phases.MaybeAspectPhase], + // Dependency[chisel3.stage.phases.MaybeAspectPhase], Dependency[chisel3.stage.phases.Convert] ) } @@ -179,7 +179,7 @@ object ChiselStage { override val targets = Seq( Dependency[chisel3.stage.phases.AddImplicitOutputFile], Dependency[chisel3.stage.phases.AddImplicitOutputAnnotationFile], - Dependency[chisel3.stage.phases.MaybeAspectPhase], + // Dependency[chisel3.stage.phases.MaybeAspectPhase], Dependency[chisel3.stage.phases.Convert] ) } @@ -207,7 +207,7 @@ object ChiselStage { Dependency[chisel3.stage.phases.Elaborate], Dependency[chisel3.stage.phases.AddImplicitOutputFile], Dependency[chisel3.stage.phases.AddImplicitOutputAnnotationFile], - Dependency[chisel3.stage.phases.MaybeAspectPhase], + // Dependency[chisel3.stage.phases.MaybeAspectPhase], Dependency[chisel3.stage.phases.Convert], Dependency[firrtl.stage.phases.Compiler] ) @@ -233,7 +233,7 @@ object ChiselStage { Dependency[chisel3.stage.phases.Elaborate], Dependency[chisel3.stage.phases.AddImplicitOutputFile], Dependency[chisel3.stage.phases.AddImplicitOutputAnnotationFile], - Dependency[chisel3.stage.phases.MaybeAspectPhase], + // Dependency[chisel3.stage.phases.MaybeAspectPhase], Dependency[chisel3.stage.phases.Convert], Dependency[firrtl.stage.phases.Compiler] ) @@ -258,7 +258,7 @@ object ChiselStage { Dependency[chisel3.stage.phases.Elaborate], Dependency[chisel3.stage.phases.AddImplicitOutputFile], Dependency[chisel3.stage.phases.AddImplicitOutputAnnotationFile], - Dependency[chisel3.stage.phases.MaybeAspectPhase], + // Dependency[chisel3.stage.phases.MaybeAspectPhase], Dependency[chisel3.stage.phases.Convert], Dependency[firrtl.stage.phases.Compiler] ) diff --git a/src/main/scala/chisel3/stage/phases/AspectPhase.scala b/src/main/scala/chisel3/stage/phases/AspectPhase.scala index efe2c3a4..414dc075 100644 --- a/src/main/scala/chisel3/stage/phases/AspectPhase.scala +++ b/src/main/scala/chisel3/stage/phases/AspectPhase.scala @@ -1,36 +1,36 @@ -// SPDX-License-Identifier: Apache-2.0 +// // SPDX-License-Identifier: Apache-2.0 -package chisel3.stage.phases +// package chisel3.stage.phases -import chisel3.aop.Aspect -import chisel3.RawModule -import chisel3.stage.DesignAnnotation -import firrtl.AnnotationSeq -import firrtl.options.Phase +// import chisel3.aop.Aspect +// import chisel3.RawModule +// import chisel3.stage.DesignAnnotation +// import firrtl.AnnotationSeq +// import firrtl.options.Phase -import scala.collection.mutable +// import scala.collection.mutable -/** Phase that consumes all Aspects and calls their toAnnotationSeq methods. - * - * Consumes the [[chisel3.stage.DesignAnnotation]] and converts every [[Aspect]] into their annotations prior to executing FIRRTL - */ -class AspectPhase extends Phase { - def transform(annotations: AnnotationSeq): AnnotationSeq = { - var dut: Option[RawModule] = None - val aspects = mutable.ArrayBuffer[Aspect[_]]() +// /** Phase that consumes all Aspects and calls their toAnnotationSeq methods. +// * +// * Consumes the [[chisel3.stage.DesignAnnotation]] and converts every [[Aspect]] into their annotations prior to executing FIRRTL +// */ +// class AspectPhase extends Phase { +// def transform(annotations: AnnotationSeq): AnnotationSeq = { +// var dut: Option[RawModule] = None +// val aspects = mutable.ArrayBuffer[Aspect[_]]() - val remainingAnnotations = annotations.flatMap { - case DesignAnnotation(d) => - dut = Some(d) - Nil - case a: Aspect[_] => - aspects += a - Nil - case other => Seq(other) - } - if (dut.isDefined) { - val newAnnotations = aspects.flatMap { _.resolveAspect(dut.get, remainingAnnotations) } - remainingAnnotations ++ newAnnotations - } else annotations - } -} +// val remainingAnnotations = annotations.flatMap { +// case DesignAnnotation(d) => +// dut = Some(d) +// Nil +// case a: Aspect[_] => +// aspects += a +// Nil +// case other => Seq(other) +// } +// if (dut.isDefined) { +// val newAnnotations = aspects.flatMap { _.resolveAspect(dut.get, remainingAnnotations) } +// remainingAnnotations ++ newAnnotations +// } else annotations +// } +// } diff --git a/src/main/scala/chisel3/stage/phases/Emitter.scala b/src/main/scala/chisel3/stage/phases/Emitter.scala index 254f8add..82a24950 100644 --- a/src/main/scala/chisel3/stage/phases/Emitter.scala +++ b/src/main/scala/chisel3/stage/phases/Emitter.scala @@ -29,7 +29,7 @@ class Emitter extends Phase { Dependency[Elaborate], Dependency[AddImplicitOutputFile], Dependency[AddImplicitOutputAnnotationFile], - Dependency[MaybeAspectPhase] + // Dependency[MaybeAspectPhase] ) override def optionalPrerequisites = Seq.empty override def optionalPrerequisiteOf = Seq(Dependency[Convert]) diff --git a/src/main/scala/chisel3/stage/phases/MaybeAspectPhase.scala b/src/main/scala/chisel3/stage/phases/MaybeAspectPhase.scala index dcd0dfe0..0afebd3b 100644 --- a/src/main/scala/chisel3/stage/phases/MaybeAspectPhase.scala +++ b/src/main/scala/chisel3/stage/phases/MaybeAspectPhase.scala @@ -1,23 +1,23 @@ -// SPDX-License-Identifier: Apache-2.0 +// // SPDX-License-Identifier: Apache-2.0 -package chisel3.stage.phases +// package chisel3.stage.phases -import chisel3.aop.Aspect -import firrtl.AnnotationSeq -import firrtl.options.{Dependency, Phase} +// import chisel3.aop.Aspect +// import firrtl.AnnotationSeq +// import firrtl.options.{Dependency, Phase} -/** Run [[AspectPhase]] if a [[chisel3.aop.Aspect]] is present. - */ -class MaybeAspectPhase extends Phase { +// /** Run [[AspectPhase]] if a [[chisel3.aop.Aspect]] is present. +// */ +// class MaybeAspectPhase extends Phase { - override def prerequisites = Seq(Dependency[Elaborate]) - override def optionalPrerequisites = Seq.empty - override def optionalPrerequisiteOf = Seq.empty - override def invalidates(a: Phase) = false +// override def prerequisites = Seq(Dependency[Elaborate]) +// override def optionalPrerequisites = Seq.empty +// override def optionalPrerequisiteOf = Seq.empty +// override def invalidates(a: Phase) = false - def transform(annotations: AnnotationSeq): AnnotationSeq = { - if (annotations.collectFirst { case a: Aspect[_] => annotations }.isDefined) { - new AspectPhase().transform(annotations) - } else annotations - } -} +// def transform(annotations: AnnotationSeq): AnnotationSeq = { +// if (annotations.collectFirst { case a: Aspect[_] => annotations }.isDefined) { +// new AspectPhase().transform(annotations) +// } else annotations +// } +// } diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index f8c8f9e9..aa223697 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -22,7 +22,7 @@ import scala.annotation.nowarn 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: Module)) if !module.compileOptions.declaredTypeMustBeUnbound => chiselTypeOf(gen) + // case (true, Some(module: Module)) if !module.compileOptions.declaredTypeMustBeUnbound => chiselTypeOf(gen) case _ => gen } diff --git a/src/test/scala/chiselTests/AbstractModule.scala b/src/test/scala/chiselTests/AbstractModule.scala new file mode 100644 index 00000000..dc381120 --- /dev/null +++ b/src/test/scala/chiselTests/AbstractModule.scala @@ -0,0 +1,20 @@ +package chiselTests + +import chisel3._ +import chisel3.stage.ChiselStage + +class AbstractModule[T <: Data](params: T) extends Module[T] { + val node = IO(params) +} + +class AbstractModuleContainer extends Module { + val mod1 = Module(new AbstractModule[UInt](Input(UInt(0.W)))) + val mod2 = Module(new AbstractModule[UInt](Output(UInt(0.W)))) + mod2.node := mod1.node +} + +class AbstractModuleSpec extends ChiselPropSpec with Utils { + property("Abstract module should elaborate") { + ChiselStage.elaborate { new AbstractModuleContainer } + } +} diff --git a/src/test/scala/chiselTests/AdderTree.scala b/src/test/scala/chiselTests/AdderTree.scala deleted file mode 100644 index 29ef97a4..00000000 --- a/src/test/scala/chiselTests/AdderTree.scala +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.testers.BasicTester - -class AdderTree[T <: Bits with Num[T]](genType: T, vecSize: Int) extends Module { - val io = IO(new Bundle { - val numIn = Input(Vec(vecSize, genType)) - val numOut = Output(genType) - }) - io.numOut := io.numIn.reduceTree((a: T, b: T) => (a + b)) -} - -class AdderTreeTester(bitWidth: Int, numsToAdd: List[Int]) extends BasicTester { - val genType = UInt(bitWidth.W) - val dut = Module(new AdderTree(genType, numsToAdd.size)) - dut.io.numIn := VecInit(numsToAdd.map(x => x.asUInt(bitWidth.W))) - val sumCorrect = dut.io.numOut === (numsToAdd.reduce(_ + _) % (1 << bitWidth)).asUInt(bitWidth.W) - assert(sumCorrect) - stop() -} - -class AdderTreeSpec extends ChiselPropSpec { - property("All numbers should be added correctly by an Adder Tree") { - forAll(safeUIntN(20)) { - case (w: Int, v: List[Int]) => { - whenever(v.size > 0 && w > 0) { - assertTesterPasses { new AdderTreeTester(w, v.map(x => math.abs(x) % (1 << w)).toList) } - } - } - } - } -} diff --git a/src/test/scala/chiselTests/AnalogIntegrationSpec.scala b/src/test/scala/chiselTests/AnalogIntegrationSpec.scala deleted file mode 100644 index 035a9d91..00000000 --- a/src/test/scala/chiselTests/AnalogIntegrationSpec.scala +++ /dev/null @@ -1,150 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.util._ -import chisel3.testers.{BasicTester, TesterDriver} -import chisel3.experimental._ - -/* This test is different from AnalogSpec in that it uses more complicated black boxes that can each - * drive the bidirectional bus. It was created to evaluate Analog with synthesis tools since the - * simple tests in AnalogSpec don't anything interesting in them to synthesize. - */ - -class AnalogBlackBoxPort extends Bundle { - val in = Input(Valid(UInt(32.W))) - val out = Output(UInt(32.W)) -} - -// This IO can be used for a single BlackBox or to group multiple -// Has multiple ports for driving and checking but only one shared bus -class AnalogBlackBoxIO(val n: Int) extends Bundle { - require(n > 0) - val bus = Analog(32.W) - val port = Vec(n, new AnalogBlackBoxPort) -} - -// Assigns bus to out -// Assigns in.bits + index to bus when in.valid -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 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 AnalogBlackBoxModuleIntf { - require(n > 0) - val io = IO(new AnalogBlackBoxIO(n)) - val bbs = idxs.map(i => Module(new AnalogBlackBoxModule(i))) - io.bus <> bbs.head.io.bus // Always bulk connect io.bus to first bus - io.port <> bbs.flatMap(_.io.port) // Connect ports - attach(bbs.map(_.io.bus): _*) // Attach all the buses -} - -// Common superclass for AnalogDUT and AnalogSmallDUT -abstract class AnalogDUTModule(numBlackBoxes: Int) extends Module { - require(numBlackBoxes > 0) - val io = IO(new Bundle { - val ports = Vec(numBlackBoxes, new AnalogBlackBoxPort) - }) -} - -/** Single test case for lots of things - * - * $ - Wire at top connecting child inouts (Done in AnalogDUT) - * $ - Port inout connected to 1 or more children inouts (AnalogBackBoxWrapper) - * $ - Multiple port inouts connected (AnalogConnector) - */ -class AnalogDUT extends AnalogDUTModule(5) { // 5 BlackBoxes - val mods = Seq( - Module(new AnalogBlackBoxWrapper(1, Seq(0))), - Module(new AnalogBlackBoxModule(1)), - Module(new AnalogBlackBoxWrapper(2, Seq(2, 3))), // 2 blackboxes - Module(new AnalogBlackBoxModule(4)) - ) - // Connect all ports to top - io.ports <> mods.flatMap(_.io.port) - // Attach first 3 Modules - attach(mods.take(3).map(_.io.bus): _*) - // Attach last module to 1st through AnalogConnector - val con = Module(new AnalogConnector) - attach(con.io.bus1, mods.head.io.bus) - attach(con.io.bus2, mods.last.io.bus) -} - -/** Same as [[AnalogDUT]] except it omits [[AnalogConnector]] because that is currently not - * supported by Verilator - * @todo Delete once Verilator can handle [[AnalogDUT]] - */ -class AnalogSmallDUT extends AnalogDUTModule(4) { // 4 BlackBoxes - val mods = Seq( - Module(new AnalogBlackBoxWrapper(1, Seq(0))), - Module(new AnalogBlackBoxModule(1)), - Module(new AnalogBlackBoxWrapper(2, Seq(2, 3))) // 2 BlackBoxes - ) - // Connect all ports to top - io.ports <> mods.flatMap(_.io.port) - // Attach first 3 Modules - attach(mods.take(3).map(_.io.bus): _*) -} - -// This tester is primarily intended to be able to pass the dut to synthesis -class AnalogIntegrationTester(mod: => AnalogDUTModule) extends BasicTester { - val BusValue = 2.U(32.W) // arbitrary - - val dut = Module(mod) - - val expectedValue = Wire(UInt(32.W)) - expectedValue := BusValue // Overridden each cycle - - val (cycle, done) = Counter(true.B, dut.io.ports.size) - for ((dut, idx) <- dut.io.ports.zipWithIndex) { - printf(p"@$cycle: BlackBox #$idx: $dut\n") - // Defaults - dut.in.valid := false.B - dut.in.bits := BusValue - // Error checking - assert(dut.out === expectedValue) - - when(cycle === idx.U) { - expectedValue := BusValue + idx.U - dut.in.valid := true.B - - } - } - when(done) { stop() } -} - -class AnalogIntegrationSpec extends ChiselFlatSpec { - behavior.of("Verilator") - it should "support simple bidirectional wires" in { - assertTesterPasses( - new AnalogIntegrationTester(new AnalogSmallDUT), - Seq("/chisel3/AnalogBlackBox.v"), - TesterDriver.verilatorOnly - ) - } - // Use this test once Verilator supports alias - ignore should "support arbitrary bidirectional wires" in { - assertTesterPasses( - new AnalogIntegrationTester(new AnalogDUT), - Seq("/chisel3/AnalogBlackBox.v"), - TesterDriver.verilatorOnly - ) - } -} diff --git a/src/test/scala/chiselTests/AnalogSpec.scala b/src/test/scala/chiselTests/AnalogSpec.scala deleted file mode 100644 index 3d03af78..00000000 --- a/src/test/scala/chiselTests/AnalogSpec.scala +++ /dev/null @@ -1,352 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.util._ -import chisel3.testers.{BasicTester, TesterDriver} -import chisel3.experimental.{attach, Analog, BaseModule} - -// IO for Modules that just connect bus to out -class AnalogReaderIO extends Bundle { - val bus = Analog(32.W) - val out = Output(UInt(32.W)) -} -// IO for Modules that drive bus from in (there should be only 1) -class AnalogWriterIO extends Bundle { - val bus = Analog(32.W) - val in = Input(UInt(32.W)) -} - -trait AnalogReader { - def out: UInt - def bus: Analog -} - -class AnalogReaderBlackBox extends BlackBox with AnalogReader { - val io = IO(new AnalogReaderIO) - def out = io.out - def bus = io.bus -} - -class AnalogReaderWrapper extends Module with AnalogReader { - val io = IO(new AnalogReaderIO) - def out = io.out - def bus = io.bus - val mod = Module(new AnalogReaderBlackBox) - io <> mod.io -} -class AnalogWriterBlackBox extends BlackBox { - val io = IO(new AnalogWriterIO) -} -// Connects two Analog ports -class AnalogConnector extends Module { - val io = IO(new Bundle { - val bus1 = Analog(32.W) - val bus2 = Analog(32.W) - }) - io.bus1 <> io.bus2 -} - -class VecAnalogReaderWrapper extends RawModule with AnalogReader { - val vecbus = IO(Vec(1, Analog(32.W))) - val out = IO(Output(UInt(32.W))) - val mod = Module(new AnalogReaderBlackBox) - def bus = vecbus(0) - mod.io.bus <> bus - out := mod.io.out -} - -class VecBundleAnalogReaderWrapper extends RawModule with AnalogReader { - val vecBunBus = IO( - Vec( - 1, - new Bundle { - val analog = Analog(32.W) - } - ) - ) - def bus = vecBunBus(0).analog - val out = IO(Output(UInt(32.W))) - val mod = Module(new AnalogReaderBlackBox) - mod.io.bus <> bus - out := mod.io.out -} - -// Parent class for tests connecing up AnalogReaders and AnalogWriters -abstract class AnalogTester extends BasicTester { - final val BusValue = "hdeadbeef".U - - final val (cycle, done) = Counter(true.B, 2) - when(done) { stop() } - - final val writer = Module(new AnalogWriterBlackBox) - writer.io.in := BusValue - - final def check(reader: BaseModule with AnalogReader): Unit = - assert(reader.out === BusValue) -} - -class AnalogSpec extends ChiselFlatSpec with Utils { - behavior.of("Analog") - - it should "NOT be bindable to registers" in { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { - new Module { - val io = IO(new Bundle {}) - val reg = Reg(Analog(32.W)) - } - } - } - } - - it should "NOT be bindable to a direction" in { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { - new Module { - val io = IO(new Bundle { - val a = Input(Analog(32.W)) - }) - } - } - } - a[ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { - new Module { - val io = IO(new Bundle { - val a = Output(Analog(32.W)) - }) - } - } - } - } - - it should "be flippable" in { - ChiselStage.elaborate { - new Module { - val io = IO(new Bundle { - val a = Flipped(Analog(32.W)) - }) - } - } - } - - // There is no binding on the type of a memory - // Should this be an error? - ignore should "NOT be a legal type for Mem" in { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { - new Module { - val io = IO(new Bundle {}) - val mem = Mem(16, Analog(32.W)) - } - } - } - } - - it should "NOT be bindable to Mem ports" in { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { - new Module { - val io = IO(new Bundle {}) - val mem = Mem(16, Analog(32.W)) - val port = mem(5.U) - } - } - } - } - - // TODO This should probably be caught in Chisel - // Also note this relies on executing Firrtl from Chisel directly - it should "NOT be connectable to UInts" in { - a[Exception] should be thrownBy { - runTester { - new BasicTester { - val uint = WireDefault(0.U(32.W)) - val sint = Wire(Analog(32.W)) - sint := uint - } - } - } - } - - it should "work with 2 blackboxes bulk connected" in { - assertTesterPasses( - new AnalogTester { - val mod = Module(new AnalogReaderBlackBox) - mod.io.bus <> writer.io.bus - check(mod) - }, - Seq("/chisel3/AnalogBlackBox.v"), - TesterDriver.verilatorOnly - ) - } - - it should "error if any bulk connected more than once" in { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle {}) - val wires = List.fill(3)(Wire(Analog(32.W))) - wires(0) <> wires(1) - wires(0) <> wires(2) - }) - } - a[ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle {}) - val wires = List.fill(2)(Wire(Analog(32.W))) - wires(0) <> DontCare - wires(0) <> wires(1) - }) - } - } - - it should "allow DontCare connection" in { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val a = Analog(1.W) - }) - io.a := DontCare - }) - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val a = Analog(1.W) - }) - io.a <> DontCare - }) - } - - it should "work in bidirectional Aggregate wires" in { - class MyBundle extends Bundle { - val x = Input(UInt(8.W)) - val y = Analog(8.W) - } - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val a = new MyBundle - }) - val w = Wire(new MyBundle) - w <> io.a - }) - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val a = Vec(1, new MyBundle) - }) - val w = Wire(Vec(1, new MyBundle)) - w <> io.a - }) - } - - it should "work with 3 blackboxes attached" in { - assertTesterPasses( - new AnalogTester { - val mods = Seq.fill(2)(Module(new AnalogReaderBlackBox)) - attach(writer.io.bus, mods(0).io.bus, mods(1).io.bus) - mods.foreach(check(_)) - }, - Seq("/chisel3/AnalogBlackBox.v"), - TesterDriver.verilatorOnly - ) - } - - it should "work with 3 blackboxes separately attached via a wire" in { - assertTesterPasses( - new AnalogTester { - val mods = Seq.fill(2)(Module(new AnalogReaderBlackBox)) - val busWire = Wire(Analog(32.W)) - attach(busWire, writer.io.bus) - attach(busWire, mods(0).io.bus) - attach(mods(1).io.bus, busWire) - mods.foreach(check(_)) - }, - Seq("/chisel3/AnalogBlackBox.v"), - TesterDriver.verilatorOnly - ) - } - - // This does not currently work in Verilator unless Firrtl does constant prop and dead code - // elimination on these wires - ignore should "work with intermediate wires attached to each other" in { - assertTesterPasses( - new AnalogTester { - val mod = Module(new AnalogReaderBlackBox) - val busWire = Seq.fill(2)(Wire(Analog(32.W))) - attach(busWire(0), writer.io.bus) - attach(busWire(1), mod.io.bus) - attach(busWire(0), busWire(1)) - check(mod) - }, - Seq("/chisel3/AnalogBlackBox.v"), - TesterDriver.verilatorOnly - ) - } - - it should "work with blackboxes at different levels of the module hierarchy" in { - assertTesterPasses( - new AnalogTester { - val mods = Seq(Module(new AnalogReaderBlackBox), Module(new AnalogReaderWrapper)) - val busWire = Wire(writer.io.bus.cloneType) - attach(writer.io.bus, mods(0).bus, mods(1).bus) - mods.foreach(check(_)) - }, - Seq("/chisel3/AnalogBlackBox.v"), - TesterDriver.verilatorOnly - ) - } - - // This does not currently work in Verilator, but does work in VCS - ignore should "support two analog ports in the same module" in { - assertTesterPasses( - new AnalogTester { - val reader = Module(new AnalogReaderBlackBox) - val connector = Module(new AnalogConnector) - connector.io.bus1 <> writer.io.bus - reader.io.bus <> connector.io.bus2 - check(reader) - }, - Seq("/chisel3/AnalogBlackBox.v"), - TesterDriver.verilatorOnly - ) - } - - it should "NOT support conditional connection of analog types" in { - a[ChiselException] should be thrownBy { - assertTesterPasses( - new AnalogTester { - val mod = Module(new AnalogReaderBlackBox) - when(cycle > 3.U) { - mod.io.bus <> writer.io.bus - } - check(mod) - }, - Seq("/chisel3/AnalogBlackBox.v") - ) - } - } - - it should "work with Vecs of Analog" in { - assertTesterPasses( - new AnalogTester { - val mod = Module(new VecAnalogReaderWrapper) - mod.bus <> writer.io.bus - check(mod) - }, - Seq("/chisel3/AnalogBlackBox.v"), - TesterDriver.verilatorOnly - ) - } - - it should "work with Vecs of Bundles of Analog" in { - assertTesterPasses( - new AnalogTester { - val mod = Module(new VecBundleAnalogReaderWrapper) - mod.bus <> writer.io.bus - check(mod) - }, - Seq("/chisel3/AnalogBlackBox.v"), - TesterDriver.verilatorOnly - ) - } -} diff --git a/src/test/scala/chiselTests/AnnotatingDiamondSpec.scala b/src/test/scala/chiselTests/AnnotatingDiamondSpec.scala deleted file mode 100644 index af73d5d4..00000000 --- a/src/test/scala/chiselTests/AnnotatingDiamondSpec.scala +++ /dev/null @@ -1,166 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.experimental.{annotate, ChiselAnnotation, RunFirrtlTransform} -import chisel3.internal.InstanceId -import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} -import chisel3.testers.BasicTester -import firrtl.{CircuitForm, CircuitState, DependencyAPIMigration, LowForm, Transform} -import firrtl.annotations.{CircuitName, CircuitTarget, SingleTargetAnnotation, Target} -import firrtl.stage.Forms -import org.scalatest._ -import org.scalatest.freespec.AnyFreeSpec -import org.scalatest.matchers.should.Matchers - -/** These annotations and the IdentityTransform class serve as an example of how to write a - * Chisel/Firrtl library - */ -case class IdentityAnnotation(target: Target, value: String) extends SingleTargetAnnotation[Target] { - def duplicate(n: Target): IdentityAnnotation = this.copy(target = n) -} - -/** ChiselAnnotation that corresponds to the above FIRRTL annotation */ -case class IdentityChiselAnnotation(target: InstanceId, value: String) - extends ChiselAnnotation - with RunFirrtlTransform { - def toFirrtl: IdentityAnnotation = IdentityAnnotation(target.toNamed, value) - def transformClass: Class[IdentityTransform] = classOf[IdentityTransform] -} -object identify { - def apply(component: InstanceId, value: String): Unit = { - val anno = IdentityChiselAnnotation(component, value) - annotate(anno) - } -} - -class IdentityTransform extends Transform with DependencyAPIMigration { - override def prerequisites = Forms.LowForm - override def optionalPrerequisites = Seq.empty - override def optionalPrerequisiteOf = Forms.LowEmitters - override def invalidates(a: Transform) = false - - def execute(state: CircuitState): CircuitState = { - val annosx = state.annotations.map { - case IdentityAnnotation(t, value) => IdentityAnnotation(t, value + ":seen") - case other => other - } - state.copy(annotations = annosx) - } -} - -/** A diamond circuit Top instantiates A and B and both A and B instantiate C - * Illustrations of annotations of various components and modules in both - * relative and absolute cases - * - * This is currently not much of a test, read the printout to see what annotations look like - */ -/** - * This class has parameterizable widths, it will generate different hardware - * @param widthC io width - */ -class ModC(widthC: Int) extends Module { - val io = IO(new Bundle { - val in = Input(UInt(widthC.W)) - val out = Output(UInt(widthC.W)) - }) - io.out := io.in - - identify(this, s"ModC($widthC)") - - identify(io.out, s"ModC(ignore param)") -} - -/** - * instantiates a C of a particular size, ModA does not generate different hardware - * based on it's parameter - * @param annoParam parameter is only used in annotation not in circuit - */ -class ModA(annoParam: Int) extends Module { - val io = IO(new Bundle { - val in = Input(UInt()) - val out = Output(UInt()) - }) - val modC = Module(new ModC(16)) - modC.io.in := io.in - io.out := modC.io.out - - identify(this, s"ModA(ignore param)") - - identify(io.out, s"ModA.io.out($annoParam)") - identify(io.out, s"ModA.io.out(ignore_param)") -} - -class ModB(widthB: Int) extends Module { - val io = IO(new Bundle { - val in = Input(UInt(widthB.W)) - val out = Output(UInt(widthB.W)) - }) - val modC = Module(new ModC(widthB)) - modC.io.in := io.in - io.out := modC.io.out - - identify(io.in, s"modB.io.in annotated from inside modB") -} - -class TopOfDiamond extends Module { - val io = IO(new Bundle { - val in = Input(UInt(32.W)) - val out = Output(UInt(32.W)) - }) - val x = Reg(UInt(32.W)) - val y = Reg(UInt(32.W)) - - val modA = Module(new ModA(64)) - val modB = Module(new ModB(32)) - - x := io.in - modA.io.in := x - modB.io.in := x - - y := modA.io.out + modB.io.out - io.out := y - - identify(this, s"TopOfDiamond\nWith\nSome new lines") - - identify(modB.io.in, s"modB.io.in annotated from outside modB") -} - -class DiamondTester extends BasicTester { - val dut = Module(new TopOfDiamond) - - stop() -} - -class AnnotatingDiamondSpec extends AnyFreeSpec with Matchers { - - """|Diamond is an example of a module that has two sub-modules A and B who both instantiate their - |own instances of module C. This highlights the difference between specific and general - |annotation scopes""".stripMargin - { - - """|annotations are not resolved at after circuit elaboration, - |that happens only after emit has been called on circuit""".stripMargin in { - - val annos = (new ChiselStage) - .execute( - Array("--target-dir", "test_run_dir", "--no-run-firrtl"), - Seq(ChiselGeneratorAnnotation(() => new TopOfDiamond)) - ) - .filter { - case _: IdentityAnnotation => true - case _ => false - } - .toSeq - - info("Found ten (10) 'IdentityAnnotation's") - (annos should have).length(10) - - info("Found IdentityAnnotation targeting '~*|ModC' with value 'ModC(16)'") - annos should contain(IdentityAnnotation(CircuitTarget("TopOfDiamond").module("ModC"), "ModC(16)")) - - info("Found IdentityAnnotation targeting '~*|ModC_1:seen' with value 'ModC(32)'") - annos should contain(IdentityAnnotation(CircuitTarget("TopOfDiamond").module("ModC_1"), "ModC(32)")) - } - } -} diff --git a/src/test/scala/chiselTests/AnnotationNoDedup.scala b/src/test/scala/chiselTests/AnnotationNoDedup.scala deleted file mode 100644 index 2150f925..00000000 --- a/src/test/scala/chiselTests/AnnotationNoDedup.scala +++ /dev/null @@ -1,79 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.experimental.doNotDedup -import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} -import firrtl.stage.FirrtlCircuitAnnotation -import org.scalatest.freespec.AnyFreeSpec -import org.scalatest.matchers.should.Matchers - -class MuchUsedModule extends Module { - val io = IO(new Bundle { - val in = Input(UInt(16.W)) - val out = Output(UInt(16.W)) - }) - io.out := io.in +% 1.U -} - -class UsesMuchUsedModule(addAnnos: Boolean) extends Module { - val io = IO(new Bundle { - val in = Input(UInt(16.W)) - val out = Output(UInt(16.W)) - }) - - val mod0 = Module(new MuchUsedModule) - val mod1 = Module(new MuchUsedModule) - val mod2 = Module(new MuchUsedModule) - val mod3 = Module(new MuchUsedModule) - - mod0.io.in := io.in - mod1.io.in := mod0.io.out - mod2.io.in := mod1.io.out - mod3.io.in := mod2.io.out - io.out := mod3.io.out - - if (addAnnos) { - doNotDedup(mod1) - doNotDedup(mod3) - } -} - -class AnnotationNoDedup extends AnyFreeSpec with Matchers { - val stage = new ChiselStage - "Firrtl provides transform that reduces identical modules to a single instance" - { - "Annotations can be added which will prevent this deduplication for specific modules instances" in { - val lowFirrtl = stage - .execute( - Array("-X", "low", "--target-dir", "test_run_dir"), - Seq(ChiselGeneratorAnnotation(() => new UsesMuchUsedModule(addAnnos = true))) - ) - .collectFirst { - case FirrtlCircuitAnnotation(circuit) => circuit.serialize - } - .getOrElse(fail) - lowFirrtl should include("module MuchUsedModule :") - lowFirrtl should include("module MuchUsedModule_1 :") - lowFirrtl should include("module MuchUsedModule_3 :") - (lowFirrtl should not).include("module MuchUsedModule_2 :") - (lowFirrtl should not).include("module MuchUsedModule_4 :") - } - "Turning off these annotations dedups all the occurrences" in { - val lowFirrtl = stage - .execute( - Array("-X", "low", "--target-dir", "test_run_dir"), - Seq(ChiselGeneratorAnnotation(() => new UsesMuchUsedModule(addAnnos = false))) - ) - .collectFirst { - case FirrtlCircuitAnnotation(circuit) => circuit.serialize - } - .getOrElse(fail) - lowFirrtl should include("module MuchUsedModule :") - (lowFirrtl should not).include("module MuchUsedModule_1 :") - (lowFirrtl should not).include("module MuchUsedModule_3 :") - (lowFirrtl should not).include("module MuchUsedModule_2 :") - (lowFirrtl should not).include("module MuchUsedModule_4 :") - } - } -} diff --git a/src/test/scala/chiselTests/AsTypeOfTester.scala b/src/test/scala/chiselTests/AsTypeOfTester.scala deleted file mode 100644 index a1668914..00000000 --- a/src/test/scala/chiselTests/AsTypeOfTester.scala +++ /dev/null @@ -1,155 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.experimental.{DataMirror, FixedPoint} -import chisel3.testers.BasicTester - -class AsTypeOfBundleTester extends BasicTester { - class MultiTypeBundle extends Bundle { - val u = UInt(4.W) - val s = SInt(4.W) - val fp = FixedPoint(4.W, 3.BP) - } - - val bun = new MultiTypeBundle - - val bunAsTypeOf = ((4 << 8) + (15 << 4) + (12 << 0)).U.asTypeOf(bun) - - assert(bunAsTypeOf.u === 4.U) - assert(bunAsTypeOf.s === -1.S) - assert(bunAsTypeOf.fp === FixedPoint.fromDouble(-0.5, 4.W, 3.BP)) - - stop() -} - -class AsTypeOfBundleZeroWidthTester extends BasicTester { - class ZeroWidthBundle extends Bundle { - val a = UInt(0.W) - val b = UInt(1.W) - val c = UInt(0.W) - } - - val bun = new ZeroWidthBundle - - val bunAsTypeOf = 1.U.asTypeOf(bun) - - assert(bunAsTypeOf.a === 0.U) - assert(bunAsTypeOf.b === 1.U) - assert(bunAsTypeOf.c === 0.U) - - stop() -} - -class AsTypeOfVecTester extends BasicTester { - val vec = ((15 << 12) + (0 << 8) + (1 << 4) + (2 << 0)).U.asTypeOf(Vec(4, SInt(4.W))) - - assert(vec(0) === 2.S) - assert(vec(1) === 1.S) - assert(vec(2) === 0.S) - assert(vec(3) === -1.S) - - stop() -} - -class AsTypeOfTruncationTester extends BasicTester { - val truncate = (64 + 3).U.asTypeOf(UInt(3.W)) - val expand = 1.U.asTypeOf(UInt(3.W)) - - assert(DataMirror.widthOf(truncate).get == 3) - assert(truncate === 3.U) - assert(DataMirror.widthOf(expand).get == 3) - assert(expand === 1.U) - - stop() -} - -class ResetAsTypeOfBoolTester extends BasicTester { - assert(reset.asTypeOf(Bool()) === reset.asBool) - stop() -} - -class AsTypeOfClockTester extends BasicTester { - class MyBundle extends Bundle { - val x = UInt(4.W) - val y = Clock() - } - assert(true.B.asTypeOf(Clock()).asUInt.asBool === true.B) - - assert(0x1f.U.asTypeOf(new MyBundle).asUInt === 0x1f.U) - stop() -} - -class AsChiselEnumTester extends BasicTester { - object MyEnum extends ChiselEnum { - val foo, bar = Value - val fizz = Value(2.U) - } - class MyBundle extends Bundle { - val a = Bool() - val b = Bool() - } - - // To - assert(2.U.asTypeOf(MyEnum()) === MyEnum.fizz) - assert(VecInit(2.U.asBools).asTypeOf(MyEnum()) === MyEnum.fizz) - assert(2.U.asTypeOf(new MyBundle).asTypeOf(MyEnum()) === MyEnum.fizz) - - // From - assert(MyEnum.foo.asUInt === 0.U) - val vec = MyEnum.bar.asTypeOf(Vec(2, Bool())) - assert(vec(0) === 1.U) - assert(vec(1) === 0.U) - val bun = MyEnum.fizz.asTypeOf(new MyBundle) - assert(bun.b === 0.U) - assert(bun.a === 1.U) - - // In aggregate - class OtherBundle extends Bundle { - val enum = MyEnum() - val foo = Bool() - } - val wire = Wire(new OtherBundle) - wire.enum := MyEnum.fizz - wire.foo := true.B - - assert(wire.asUInt === 5.U) - val other = 5.U.asTypeOf(new OtherBundle) - assert(other.enum === MyEnum.fizz) - assert(other.foo === true.B) - - stop() -} - -class AsTypeOfSpec extends ChiselFlatSpec { - behavior.of("asTypeOf") - - it should "work with Bundles containing Bits Types" in { - assertTesterPasses { new AsTypeOfBundleTester } - } - - it should "work with Bundles that have fields of zero width" in { - assertTesterPasses { new AsTypeOfBundleZeroWidthTester } - } - - it should "work with Vecs containing Bits Types" in { - assertTesterPasses { new AsTypeOfVecTester } - } - - it should "expand and truncate UInts of different width" in { - assertTesterPasses { new AsTypeOfTruncationTester } - } - - it should "work for casting implicit Reset to Bool" in { - assertTesterPasses { new ResetAsTypeOfBoolTester } - } - - it should "work for casting to and from ChiselEnums" in { - assertTesterPasses(new AsChiselEnumTester) - } - - it should "work for casting to and from Clock" in { - assertTesterPasses(new AsTypeOfClockTester) - } -} diff --git a/src/test/scala/chiselTests/Assert.scala b/src/test/scala/chiselTests/Assert.scala deleted file mode 100644 index 5e7b6496..00000000 --- a/src/test/scala/chiselTests/Assert.scala +++ /dev/null @@ -1,205 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.testers.BasicTester -import chisel3.util._ - -class FailingAssertTester() extends BasicTester { - assert(false.B) - // Wait to come out of reset - val (_, done) = Counter(!reset.asBool, 4) - when(done) { - stop() - } -} - -class SucceedingAssertTester() extends BasicTester { - assert(true.B) - // Wait to come out of reset - val (_, done) = Counter(!reset.asBool, 4) - when(done) { - stop() - } -} - -class PipelinedResetModule extends Module { - val io = IO(new Bundle {}) - val a = RegInit(0xbeef.U) - val b = RegInit(0xbeef.U) - assert(a === b) -} - -// This relies on reset being asserted for 3 or more cycles -class PipelinedResetTester extends BasicTester { - val module = Module(new PipelinedResetModule) - - module.reset := RegNext(RegNext(RegNext(reset))) - - val (_, done) = Counter(!reset.asBool, 4) - when(done) { - stop() - } -} - -class ModuloAssertTester extends BasicTester { - assert((4.U % 2.U) === 0.U) - stop() -} - -class FormattedAssertTester extends BasicTester { - val foobar = Wire(UInt(32.W)) - foobar := 123.U - assert(foobar === 123.U, "Error! Wire foobar =/= %x! This is 100%% wrong.\n", foobar) - stop() -} - -class BadUnescapedPercentAssertTester extends BasicTester { - assert(1.U === 1.U, "I'm 110% sure this is an invalid message") - stop() -} - -class PrintableFormattedAssertTester extends BasicTester { - val foobar = Wire(UInt(32.W)) - foobar := 123.U - assert(foobar === 123.U, cf"Error! Wire foobar =/= $foobar%x This is 100%% wrong.\n") - stop() -} - -class PrintableBadUnescapedPercentAssertTester extends BasicTester { - assert(1.U === 1.U, p"I'm 110% sure this is an invalid message") - stop() -} - -class PrintableAssumeTester extends Module { - val in = IO(Input(UInt(8.W))) - val out = IO(Output(UInt(8.W))) - - val w = Wire(UInt(8.W)) - w := 255.U - assume(w === 255.U, cf"Assumption failed, Wire w =/= $w%x") - - out := in -} - -class PrintableScopeTester extends Module { - val in = IO(Input(UInt(8.W))) - val out = IO(Output(UInt(8.W))) - out := in - - val w = Wire(UInt(8.W)) - w := 255.U - - val printableWire = cf"$w" - val printablePort = cf"$in" -} - -class AssertPrintableWireScope extends BasicTester { - val mod = Module(new PrintableScopeTester) - assert(1.U === 2.U, mod.printableWire) - stop() -} - -class AssertPrintablePortScope extends BasicTester { - val mod = Module(new PrintableScopeTester) - mod.in := 255.U - assert(1.U === 1.U, mod.printablePort) - stop() -} - -class AssertPrintableFailingWhenScope extends BasicTester { - val mod = Module(new PrintableWhenScopeTester) - assert(1.U === 1.U, mod.printable) - stop() -} - -class AssumePrintableWireScope extends BasicTester { - val mod = Module(new PrintableScopeTester) - assume(1.U === 1.U, mod.printableWire) - stop() -} - -class AssumePrintablePortScope extends BasicTester { - val mod = Module(new PrintableScopeTester) - mod.in := 255.U - assume(1.U === 1.U, mod.printablePort) - stop() -} - -class PrintableWhenScopeTester extends Module { - val in = IO(Input(UInt(8.W))) - val out = IO(Output(UInt(8.W))) - - out := in - - val w = Wire(UInt(8.W)) - w := 255.U - var printable = cf"" - when(true.B) { - printable = cf"$w" - } -} - -class AssertSpec extends ChiselFlatSpec with Utils { - "A failing assertion" should "fail the testbench" in { - assert(!runTester { new FailingAssertTester }) - } - "A succeeding assertion" should "not fail the testbench" in { - assertTesterPasses { new SucceedingAssertTester } - } - "An assertion" should "not assert until we come out of reset" in { - assertTesterPasses { new PipelinedResetTester } - } - - "Assert Printables" should "respect port scoping" in { - assertTesterPasses { new AssertPrintablePortScope } - } - "Assert Printables" should "respect wire scoping" in { - a[ChiselException] should be thrownBy { ChiselStage.elaborate(new AssertPrintableWireScope) } - } - "Assume Printables" should "respect port scoping" in { - assertTesterPasses { new AssumePrintablePortScope } - } - - "Assume Printables" should "respect wire scoping" in { - a[ChiselException] should be thrownBy { ChiselStage.elaborate(new AssumePrintableWireScope) } - } - - "Assert Printables" should "respect when scope" in { - a[ChiselException] should be thrownBy { ChiselStage.elaborate(new AssertPrintableFailingWhenScope) } - } - - "Assertions" should "allow the modulo operator % in the message" in { - assertTesterPasses { new ModuloAssertTester } - } - they should "allow printf-style format strings with arguments" in { - assertTesterPasses { new FormattedAssertTester } - } - they should "allow printf-style format strings in Assumes" in { - val chirrtl = ChiselStage.emitChirrtl(new PrintableAssumeTester) - chirrtl should include( - """assume(w === 255.U, cf\"Assumption failed, Wire w =/= $w%%%%x\")\n", w)""" - ) - } - they should "not allow unescaped % in the message" in { - a[java.util.UnknownFormatConversionException] should be thrownBy { - extractCause[java.util.UnknownFormatConversionException] { - ChiselStage.elaborate { new BadUnescapedPercentAssertTester } - } - } - } - - they should "allow printable format strings with arguments" in { - assertTesterPasses { new FormattedAssertTester } - } - they should "not allow unescaped % in the printable message" in { - a[java.util.UnknownFormatConversionException] should be thrownBy { - extractCause[java.util.UnknownFormatConversionException] { - ChiselStage.elaborate { new BadUnescapedPercentAssertTester } - } - } - } - -} diff --git a/src/test/scala/chiselTests/AsyncResetSpec.scala b/src/test/scala/chiselTests/AsyncResetSpec.scala deleted file mode 100644 index ac7ae0d1..00000000 --- a/src/test/scala/chiselTests/AsyncResetSpec.scala +++ /dev/null @@ -1,274 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.util.{Counter, Queue} -import chisel3.testers.BasicTester -import firrtl.checks.CheckResets.NonLiteralAsyncResetValueException - -class AsyncResetTester extends BasicTester { - val (_, cDiv) = Counter(true.B, 4) - // First rising edge when count === 3 - val slowClk = cDiv.asClock - - val (count, done) = Counter(true.B, 16) - - val asyncResetNext = RegInit(false.B) - asyncResetNext := count === 4.U - val asyncReset = asyncResetNext.asAsyncReset - - val reg = withClockAndReset(slowClk, asyncReset) { - RegInit(123.U(8.W)) - } - reg := 5.U // Normal connection - - when(count === 3.U) { - assert(reg === 5.U) - } - when(count >= 5.U && count < 7.U) { - assert(reg === 123.U) - }.elsewhen(count >= 7.U) { - assert(reg === 5.U) - } - - when(done) { - stop() - } -} - -class AsyncResetAggregateTester extends BasicTester { - class MyBundle extends Bundle { - val x = UInt(8.W) - val y = UInt(8.W) - } - val (_, cDiv) = Counter(true.B, 4) - // First rising edge when count === 3 - val slowClk = cDiv.asClock - - val (count, done) = Counter(true.B, 16) - - val asyncResetNext = RegInit(false.B) - asyncResetNext := count === 4.U - val asyncReset = asyncResetNext.asAsyncReset - - val reg = withClockAndReset(slowClk, asyncReset) { - val init = Wire(Vec(2, new MyBundle)) - init(0).x := 0.U - init(0).y := 0.U - init(1).x := 0.U - init(1).y := 0.U - RegInit(init) - } - reg(0).x := 5.U // Normal connections - reg(0).y := 6.U - reg(1).x := 7.U - reg(1).y := 8.U - - when(count === 3.U) { - assert(reg(0).x === 5.U) - assert(reg(0).y === 6.U) - assert(reg(1).x === 7.U) - assert(reg(1).y === 8.U) - } - when(count >= 5.U && count < 7.U) { - assert(reg(0).x === 0.U) - assert(reg(0).y === 0.U) - assert(reg(1).x === 0.U) - assert(reg(1).y === 0.U) - }.elsewhen(count >= 7.U) { - assert(reg(0).x === 5.U) - assert(reg(0).y === 6.U) - assert(reg(1).x === 7.U) - assert(reg(1).y === 8.U) - } - - when(done) { - stop() - } -} - -class AsyncResetQueueTester extends BasicTester { - val (_, cDiv) = Counter(true.B, 4) - val slowClk = cDiv.asClock - - val (count, done) = Counter(true.B, 16) - - val asyncResetNext = RegNext(false.B, false.B) - val asyncReset = asyncResetNext.asAsyncReset - - val queue = withClockAndReset(slowClk, asyncReset) { - Module(new Queue(UInt(8.W), 4)) - } - queue.io.enq.valid := true.B - queue.io.enq.bits := count - - queue.io.deq.ready := false.B - - val doCheck = RegNext(false.B, false.B) - when(queue.io.count === 3.U) { - asyncResetNext := true.B - doCheck := true.B - } - when(doCheck) { - assert(queue.io.count === 0.U) - } - - when(done) { - stop() - } -} - -class AsyncResetDontCareModule extends RawModule { - import chisel3.util.Valid - val monoPort = IO(Output(AsyncReset())) - monoPort := DontCare - val monoWire = Wire(AsyncReset()) - monoWire := DontCare - val monoAggPort = IO(Output(Valid(AsyncReset()))) - monoAggPort := DontCare - val monoAggWire = Wire(Valid(AsyncReset())) - monoAggWire := DontCare - - // Can't bulk connect to Wire so only ports here - val bulkPort = IO(Output(AsyncReset())) - bulkPort <> DontCare - val bulkAggPort = IO(Output(Valid(AsyncReset()))) - bulkAggPort <> DontCare -} - -class AsyncResetSpec extends ChiselFlatSpec with Utils { - - behavior.of("AsyncReset") - - it should "be able to be connected to DontCare" in { - ChiselStage.elaborate(new AsyncResetDontCareModule) - } - - it should "be allowed with literal reset values" in { - ChiselStage.elaborate(new BasicTester { - withReset(reset.asAsyncReset)(RegInit(123.U)) - }) - } - - it should "NOT be allowed with non-literal reset values" in { - a[NonLiteralAsyncResetValueException] should be thrownBy extractCause[NonLiteralAsyncResetValueException] { - compile(new BasicTester { - val x = WireInit(123.U + 456.U) - withReset(reset.asAsyncReset)(RegInit(x)) - }) - } - } - - it should "NOT be allowed to connect directly to a Bool" in { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate(new BasicTester { - val bool = Wire(Bool()) - val areset = reset.asAsyncReset - bool := areset - }) - } - } - - it should "simulate correctly" in { - assertTesterPasses(new AsyncResetTester) - } - - it should "simulate correctly with aggregates" in { - assertTesterPasses(new AsyncResetAggregateTester) - } - - it should "allow casting to and from Bool" in { - ChiselStage.elaborate(new BasicTester { - val r: Reset = reset - val a: AsyncReset = WireInit(r.asAsyncReset) - val b: Bool = a.asBool - val c: AsyncReset = b.asAsyncReset - }) - } - - it should "allow changing the reset type of whole modules like Queue" in { - assertTesterPasses(new AsyncResetQueueTester) - } - - it should "support SInt regs" in { - assertTesterPasses(new BasicTester { - // Also check that it traces through wires - val initValue = Wire(SInt()) - val reg = withReset(reset.asAsyncReset)(RegNext(initValue, 27.S)) - initValue := -43.S - val (count, done) = Counter(true.B, 4) - when(count === 0.U) { - chisel3.assert(reg === 27.S) - }.otherwise { - chisel3.assert(reg === -43.S) - } - when(done) { stop() } - }) - } - - it should "support Fixed regs" in { - assertTesterPasses(new BasicTester { - val reg = withReset(reset.asAsyncReset)(RegNext(-6.0.F(2.BP), 3.F(2.BP))) - val (count, done) = Counter(true.B, 4) - when(count === 0.U) { - chisel3.assert(reg === 3.F(2.BP)) - }.otherwise { - chisel3.assert(reg === -6.0.F(2.BP)) - } - when(done) { stop() } - }) - } - - it should "support Interval regs" in { - import chisel3.experimental._ - assertTesterPasses(new BasicTester { - val reg = withReset(reset.asAsyncReset) { - val x = RegInit(Interval(range"[0,13]"), 13.I) - x := 7.I - x - } - val (count, done) = Counter(true.B, 4) - when(count === 0.U) { - chisel3.assert(reg === 13.I) - }.otherwise { - chisel3.assert(reg === 7.I) - } - when(done) { stop() } - }) - } - - it should "allow literals cast to Bundles as reset values" in { - class MyBundle extends Bundle { - val x = UInt(16.W) - val y = UInt(16.W) - } - assertTesterPasses(new BasicTester { - val reg = withReset(reset.asAsyncReset) { - RegNext(0xbad0cad0L.U.asTypeOf(new MyBundle), 0xdeadbeefL.U.asTypeOf(new MyBundle)) - } - val (count, done) = Counter(true.B, 4) - when(count === 0.U) { - chisel3.assert(reg.asUInt === 0xdeadbeefL.U) - }.otherwise { - chisel3.assert(reg.asUInt === 0xbad0cad0L.U) - } - when(done) { stop() } - }) - } - it should "allow literals cast to Vecs as reset values" in { - assertTesterPasses(new BasicTester { - val reg = withReset(reset.asAsyncReset) { - RegNext(0xbad0cad0L.U.asTypeOf(Vec(4, UInt(8.W))), 0xdeadbeefL.U.asTypeOf(Vec(4, UInt(8.W)))) - } - val (count, done) = Counter(true.B, 4) - when(count === 0.U) { - chisel3.assert(reg.asUInt === 0xdeadbeefL.U) - }.otherwise { - chisel3.assert(reg.asUInt === 0xbad0cad0L.U) - } - when(done) { stop() } - }) - } -} diff --git a/src/test/scala/chiselTests/AutoClonetypeSpec.scala b/src/test/scala/chiselTests/AutoClonetypeSpec.scala deleted file mode 100644 index 353ae58c..00000000 --- a/src/test/scala/chiselTests/AutoClonetypeSpec.scala +++ /dev/null @@ -1,444 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.testers.TestUtils -import chisel3.util.QueueIO -import chisel3.stage.ChiselStage.elaborate -import chisel3.experimental.AutoCloneType -import scala.collection.immutable.ListMap - -class BundleWithIntArg(val i: Int) extends Bundle { - val out = UInt(i.W) -} - -class BundleWithImplicit()(implicit val ii: Int) extends Bundle { - val out = UInt(ii.W) -} - -class BundleWithArgAndImplicit(val i: Int)(implicit val ii: Int) extends Bundle { - val out1 = UInt(i.W) - val out2 = UInt(ii.W) -} - -class BaseBundleVal(val i: Int) extends Bundle { - val inner = UInt(i.W) -} -class SubBundle(i: Int, val i2: Int) extends BaseBundleVal(i) { - val inner2 = UInt(i2.W) -} -class SubBundleInvalid(i: Int, val i2: Int) extends BaseBundleVal(i + 1) { - val inner2 = UInt(i2.W) -} - -class BaseBundleNonVal(i: Int) extends Bundle { - val inner = UInt(i.W) -} -class SubBundleVal(val i: Int, val i2: Int) extends BaseBundleNonVal(i) { - val inner2 = UInt(i2.W) -} - -class ModuleWithInner extends Module { - class InnerBundle(val i: Int) extends Bundle { - val out = UInt(i.W) - } - - val io = IO(new Bundle {}) - - val myWire = Wire(new InnerBundle(14)) - require(myWire.i == 14) -} - -object CompanionObjectWithBundle { - class ParameterizedInner(val i: Int) extends Bundle { - val data = UInt(i.W) - } - class Inner extends Bundle { - val data = UInt(8.W) - } -} - -class NestedAnonymousBundle extends Bundle { - val a = Output(new Bundle { - val a = UInt(8.W) - }) -} - -// A Bundle with an argument that is also a field. -// Not necessarily good style (and not necessarily recommended), but allowed to preserve compatibility. -class BundleWithArgumentField(val x: Data, val y: Data) extends Bundle - -// Needs to be top-level so that reflective autoclonetype works -class InheritingBundle extends QueueIO(UInt(8.W), 8) { - val error = Output(Bool()) -} - -class RecordAutoCloneType[T <: Data](gen: T) extends Record with AutoCloneType { - lazy val elements = ListMap("value" -> gen) - // This is a weird thing to do, but as only Bundles have these methods, it should be legal - protected def _elementsImpl: Iterable[(String, Any)] = elements - protected def _usingPlugin = false -} - -// Records that don't mixin AutoCloneType should still be able to implement the related methods -// NOTE: This is a very weird thing to do, don't do it. -class RecordWithVerbotenMethods(w: Int) extends Record { - lazy val elements = ListMap("value" -> UInt(w.W)) - override def cloneType: this.type = (new RecordWithVerbotenMethods(w)).asInstanceOf[this.type] - // Verboten methods - protected def _usingPlugin = false - protected override def _cloneTypeImpl = this.cloneType - - protected def _elementsImpl: Iterable[(String, Any)] = Nil -} - -class AutoClonetypeSpec extends ChiselFlatSpec with Utils { - - "Bundles with Scala args" should "not need clonetype" in { - elaborate { - new Module { - val io = IO(new Bundle {}) - - val myWire = Wire(new BundleWithIntArg(8)) - assert(myWire.i == 8) - } - } - } - - "Bundles with Scala implicit args" should "not need clonetype" in { - elaborate { - new Module { - val io = IO(new Bundle {}) - - implicit val implicitInt: Int = 4 - val myWire = Wire(new BundleWithImplicit()) - - assert(myWire.ii == 4) - } - } - } - - "Bundles with Scala explicit and impicit args" should "not need clonetype" in { - elaborate { - new Module { - val io = IO(new Bundle {}) - - implicit val implicitInt: Int = 4 - val myWire = Wire(new BundleWithArgAndImplicit(8)) - - assert(myWire.i == 8) - assert(myWire.ii == 4) - } - } - } - - "Subtyped Bundles" should "not need clonetype" in { - elaborate { - new Module { - val io = IO(new Bundle {}) - - val myWire = Wire(new SubBundle(8, 4)) - - assert(myWire.i == 8) - assert(myWire.i2 == 4) - } - } - elaborate { - new Module { - val io = IO(new Bundle {}) - - val myWire = Wire(new SubBundleVal(8, 4)) - - assert(myWire.i == 8) - assert(myWire.i2 == 4) - } - } - } - - "Autoclonetype" should "work outside of a builder context" in { - new BundleWithIntArg(8).cloneType - } - - "Subtyped Bundles that don't clone well" should "be now be supported!" in { - elaborate { - new Module { - val io = IO(new Bundle {}) - val myWire = Wire(new SubBundleInvalid(8, 4)) - } - } - } - - "Inner bundles with Scala args" should "not need clonetype" in { - elaborate { new ModuleWithInner } - } - - "Bundles with arguments as fields" should "not need clonetype" in { - elaborate { - new Module { - val io = IO(Output(new BundleWithArgumentField(UInt(8.W), UInt(8.W)))) - io.x := 1.U - io.y := 1.U - } - } - } - - it should "also work when giving directions to the fields" in { - elaborate { - new Module { - val io = IO(new BundleWithArgumentField(Input(UInt(8.W)), Output(UInt(8.W)))) - io.y := io.x - } - } - } - - "Bundles inside companion objects" should "not need clonetype" in { - elaborate { - new Module { - val io = IO(Output(new CompanionObjectWithBundle.Inner)) - io.data := 1.U - } - } - } - - "Parameterized bundles inside companion objects" should "not need clonetype" in { - elaborate { - new Module { - val io = IO(Output(new CompanionObjectWithBundle.ParameterizedInner(8))) - io.data := 1.U - } - } - } - - "Nested directioned anonymous Bundles" should "not need clonetype" in { - elaborate { - new Module { - val io = IO(new NestedAnonymousBundle) - val a = WireDefault(io) - io.a.a := 1.U - } - } - } - - "3.0 null compatibility" should "not need clonetype" in { - elaborate { - new Module { - class InnerClassThing { - def createBundle: Bundle = new Bundle { - val a = Output(UInt(8.W)) - } - } - val io = IO((new InnerClassThing).createBundle) - val a = WireDefault(io) - } - } - } - - "Aliased fields" should "be caught" in { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - elaborate { - new Module { - val bundleFieldType = UInt(8.W) - val io = IO(Output(new Bundle { - val a = bundleFieldType - })) - io.a := 0.U - } - } - } - } - - "Aliased fields from inadequate autoclonetype" should "be caught" in { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - class BadBundle(val typeTuple: (Data, Int)) extends Bundle { - val a = typeTuple._1 - } - - elaborate { - new Module { - val io = IO(Output(new BadBundle(UInt(8.W), 1))) - io.a := 0.U - } - } - } - } - - "Wrapped IO construction without parent reference" should "not fail for autoclonetype" in { - class TestModule extends Module { - def thunk[T](f: => T): T = f - val works = thunk(IO(new Bundle { - val x = Output(UInt(3.W)) - })) - } - elaborate { new TestModule } - } - - "Wrapped IO construction with parent references" should "not fail for autoclonetype" in { - 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 - val broken = thunk(IO(new Bundle { - val x = Output(UInt(blah.W)) - })) - } - elaborate { new TestModule(3) } - } - - "Autoclonetype" should "support Bundles with if-blocks" in { - class MyModule(n: Int) extends MultiIOModule { - val io = IO(new Bundle { - val in = Input(UInt(8.W)) - val out = Output(UInt(8.W)) - if (n > 4) { - println("Here we are!") - } - }) - io.out := io.in - } - elaborate(new MyModule(3)) - } - - behavior.of("Compiler Plugin Autoclonetype") - - it should "NOT break code that extends chisel3.util Bundles if they use the plugin" in { - class MyModule extends MultiIOModule { - val io = IO(new InheritingBundle) - io.deq <> io.enq - io.count := 0.U - io.error := true.B - } - elaborate(new MyModule) - } - - it should "support Bundles with non-val parameters" in { - class MyBundle(i: Int) extends Bundle { - val foo = UInt(i.W) - } - elaborate { - new MultiIOModule { - val in = IO(Input(new MyBundle(8))) - val out = IO(Output(new MyBundle(8))) - out := in - } - } - } - - it should "support type-parameterized Bundles" in { - class MyBundle[T <: Data](gen: T) extends Bundle { - val foo = gen - } - elaborate { - new MultiIOModule { - val in = IO(Input(new MyBundle(UInt(8.W)))) - val out = IO(Output(new MyBundle(UInt(8.W)))) - out := in - } - } - } - - it should "support Bundles with non-val implicit parameters" in { - class MyBundle(implicit i: Int) extends Bundle { - val foo = UInt(i.W) - } - elaborate { - new MultiIOModule { - implicit val x = 8 - val in = IO(Input(new MyBundle)) - val out = IO(Output(new MyBundle)) - out := in - } - } - } - - it should "support Bundles with multiple parameter lists" in { - class MyBundle(i: Int)(j: Int, jj: Int)(k: UInt) extends Bundle { - val foo = UInt((i + j + jj + k.getWidth).W) - } - elaborate { - new MultiIOModule { - val in = IO(Input(new MyBundle(8)(8, 8)(UInt(8.W)))) - val out = IO(Output(new MyBundle(8)(8, 8)(UInt(8.W)))) - out := in - } - } - } - - it should "support Bundles that implement their own cloneType" in { - class MyBundle(i: Int) extends Bundle { - val foo = UInt(i.W) - } - elaborate { - new MultiIOModule { - val in = IO(Input(new MyBundle(8))) - val out = IO(Output(new MyBundle(8))) - out := in - } - } - } - - it should "support Bundles that capture type parameters from their parent scope" in { - class MyModule[T <: Data](gen: T) extends MultiIOModule { - class MyBundle(n: Int) extends Bundle { - val foo = Vec(n, gen) - } - val in = IO(Input(new MyBundle(4))) - val out = IO(Output(new MyBundle(4))) - out := in - } - elaborate(new MyModule(UInt(8.W))) - } - - it should "work for higher-kinded types" in { - class DataGen[T <: Data](gen: T) { - def newType: T = gen.cloneType - } - class MyBundle[A <: Data, B <: DataGen[A]](gen: B) extends Bundle { - val foo = gen.newType - } - class MyModule extends MultiIOModule { - val io = IO(Output(new MyBundle[UInt, DataGen[UInt]](new DataGen(UInt(3.W))))) - io.foo := 0.U - } - elaborate(new MyModule) - } - - it should "support Bundles with vararg arguments" in { - // Without the fix, this doesn't even compile - // Extra parameter lists to make this a complex test case - class VarArgsBundle(x: Int)(y: Int, widths: Int*) extends Bundle { - def mkField(idx: Int): Option[UInt] = - (x +: y +: widths).lift(idx).map(w => UInt(w.W)) - val foo = mkField(0) - val bar = mkField(1) - val fizz = mkField(2) - val buzz = mkField(3) - } - class MyModule extends Module { - val in = IO(Input(new VarArgsBundle(1)(2, 3, 4))) - val out = IO(Output(new VarArgsBundle(1)(2, 3, 4))) - out := in - } - elaborate(new MyModule) - } - - it should "support Records that mixin AutoCloneType" in { - class MyModule extends Module { - val gen = new RecordAutoCloneType(UInt(8.W)) - val in = IO(Input(gen)) - val out = IO(Output(gen)) - out := in - } - elaborate(new MyModule) - } - - it should "support Records that don't mixin AutoCloneType and use forbidden methods" in { - class MyModule extends Module { - val gen = new RecordWithVerbotenMethods(8) - val in = IO(Input(gen)) - val out = IO(Output(gen)) - out := in - } - elaborate(new MyModule) - } -} diff --git a/src/test/scala/chiselTests/AutoNestedCloneSpec.scala b/src/test/scala/chiselTests/AutoNestedCloneSpec.scala deleted file mode 100644 index b75c0c00..00000000 --- a/src/test/scala/chiselTests/AutoNestedCloneSpec.scala +++ /dev/null @@ -1,136 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests -import chisel3._ -import chisel3.testers.TestUtils -import chisel3.stage.ChiselStage.elaborate -import org.scalatest.matchers.should.Matchers - -class BundleWithAnonymousInner(val w: Int) extends Bundle { - val inner = new Bundle { - val foo = Input(UInt(w.W)) - } -} - -class AutoNestedCloneSpec extends ChiselFlatSpec with Matchers with Utils { - - behavior.of("autoCloneType of inner Bundle in Chisel3") - - it should "clone a doubly-nested inner bundle successfully" in { - elaborate { - class Outer(val w: Int) extends Module { - class Middle(val w: Int) { - class InnerIOType extends Bundle { - val in = Input(UInt(w.W)) - } - def getIO: InnerIOType = new InnerIOType - } - val io = IO(new Bundle {}) - val myWire = Wire((new Middle(w)).getIO) - } - new Outer(2) - } - } - - it should "clone an anonymous inner bundle successfully" in { - elaborate { - class TestTop(val w: Int) extends Module { - val io = IO(new Bundle {}) - val myWire = Wire(new Bundle { val a = UInt(w.W) }) - } - new TestTop(2) - } - } - - it should "pick the correct $outer instance for an anonymous inner bundle" in { - elaborate { - class Inner(val w: Int) extends Module { - val io = IO(new Bundle { - val in = Input(UInt(w.W)) - val out = Output(UInt(w.W)) - }) - } - class Outer(val w: Int) extends Module { - val io = IO(new Bundle { - val in = Input(UInt(w.W)) - val out = Output(UInt(w.W)) - }) - val i = Module(new Inner(w)) - val iw = Wire(chiselTypeOf(i.io)) - iw <> io - i.io <> iw - } - new Outer(2) - } - } - - it should "clone an anonymous, bound, inner bundle of another bundle successfully" in { - elaborate { - class TestModule(w: Int) extends Module { - val io = IO(new BundleWithAnonymousInner(w)) - val w0 = WireDefault(io) - val w1 = WireDefault(io.inner) - } - new TestModule(8) - } - } - - it should "clone an anonymous, inner bundle of a Module, bound to another bundle successfully" in { - elaborate { - class TestModule(w: Int) extends Module { - val bun = new Bundle { - val foo = UInt(w.W) - } - val io = IO(new Bundle { - val inner = Input(bun) - }) - val w0 = WireDefault(io) - val w1 = WireDefault(io.inner) - } - new TestModule(8) - } - } - - it should "clone a double-nested anonymous Bundle" in { - elaborate { - class TestModule() extends Module { - val io = IO(new Bundle { - val inner = Input(new Bundle { - val x = UInt(8.W) - }) - }) - } - new TestModule() - } - } - - it should "support an anonymous doubly-nested inner bundle" in { - elaborate { - class Outer(val w: Int) extends Module { - class Middle(val w: Int) { - def getIO: Bundle = new Bundle { - val in = Input(UInt(w.W)) - } - } - val io = IO(new Bundle {}) - val myWire = Wire((new Middle(w)).getIO) - } - new Outer(2) - } - } - - it should "support anonymous Inner bundles that capture type parameters from outer Bundles" in { - elaborate(new MultiIOModule { - class MyBundle[T <: Data](n: Int, gen: T) extends Bundle { - val foo = new Bundle { - val x = Input(Vec(n, gen)) - } - val bar = Output(Option(new { def mkBundle = new Bundle { val x = Vec(n, gen) } }).get.mkBundle) - } - val io = IO(new MyBundle(4, UInt(8.W))) - val myWire = WireInit(io.foo) - val myWire2 = WireInit(io.bar) - io.bar.x := io.foo.x - }) - } -} diff --git a/src/test/scala/chiselTests/BetterNamingTests.scala b/src/test/scala/chiselTests/BetterNamingTests.scala deleted file mode 100644 index 8fd1c11f..00000000 --- a/src/test/scala/chiselTests/BetterNamingTests.scala +++ /dev/null @@ -1,101 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.util._ - -import scala.collection.mutable - -// Defined outside of the class so we don't get $ in name -class Other(w: Int) extends Module { - val io = IO(new Bundle { - val a = UInt(w.W) - }) -} - -// Check the names of the Modules (not instances) -class PerNameIndexing(count: Int) extends NamedModuleTester { - def genModName(prefix: String, idx: Int): String = if (idx == 0) prefix else s"${prefix}_$idx" - val wires = Seq.tabulate(count) { i => - expectModuleName(Module(new Other(i)), genModName("Other", i)) - } - val queues = Seq.tabulate(count) { i => - expectModuleName(Module(new Queue(UInt(i.W), 16)), genModName("Queue", i)) - } -} - -// Note this only checks Iterable[Chisel.Data] which excludes Maps -class IterableNaming extends NamedModuleTester { - val seq = Seq.tabulate(3) { i => - Seq.tabulate(2) { j => expectName(WireDefault((i * j).U), s"seq_${i}_${j}") } - } - val optSet = Some( - Set( - expectName(WireDefault(0.U), "optSet_0"), - expectName(WireDefault(1.U), "optSet_1"), - expectName(WireDefault(2.U), "optSet_2"), - expectName(WireDefault(3.U), "optSet_3") - ) - ) - - val stack = { - val s = mutable.Stack[Module]() - for (i <- 0 until 4) { - val j = 3 - i - s.push(expectName(Module(new Other(i)), s"stack_$j")) - } - s - } - def streamFrom(x: Int): Stream[Module] = - expectName(Module(new Other(x)), s"list_$x") #:: streamFrom(x + 1) - val stream = streamFrom(0) // Check that we don't get into infinite loop - val list = stream.take(8).toList -} - -class DigitFieldNamesInRecord extends NamedModuleTester { - val wire = Wire(new CustomBundle("0" -> UInt(32.W), "1" -> UInt(32.W))) - expectName(wire("0"), "wire.0") - expectName(wire("1"), "wire.1") -} - -/* Better Naming Tests - * - * These tests are intended to validate that Chisel picks better names - */ -class BetterNamingTests extends ChiselFlatSpec { - - behavior.of("Better Naming") - - it should "provide unique counters for each name" in { - var module: PerNameIndexing = null - ChiselStage.elaborate { module = new PerNameIndexing(4); module } - assert(module.getNameFailures() == Nil) - } - - it should "provide names for things defined in Iterable[HasId] and Option[HasId]" in { - var module: IterableNaming = null - ChiselStage.elaborate { module = new IterableNaming; module } - assert(module.getNameFailures() == Nil) - } - - it should "allow digits to be field names in Records" in { - var module: DigitFieldNamesInRecord = null - ChiselStage.elaborate { module = new DigitFieldNamesInRecord; module } - assert(module.getNameFailures() == Nil) - } - - "Literals" should "not impact temporary name suffixes" in { - class MyModule(withLits: Boolean) extends Module { - val io = IO(new Bundle {}) - if (withLits) { - List(8.U, -3.S, 1.25.F(2.BP)) - } - WireDefault(3.U) - } - val withLits = ChiselStage.emitChirrtl(new MyModule(true)) - val noLits = ChiselStage.emitChirrtl(new MyModule(false)) - withLits should equal(noLits) - } -} diff --git a/src/test/scala/chiselTests/BitwiseOps.scala b/src/test/scala/chiselTests/BitwiseOps.scala deleted file mode 100644 index 2c050bfa..00000000 --- a/src/test/scala/chiselTests/BitwiseOps.scala +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.testers.BasicTester - -class BitwiseOpsTester(w: Int, _a: Int, _b: Int) extends BasicTester { - val mask = (1 << w) - 1 - val a = _a.asUInt(w.W) - val b = _b.asUInt(w.W) - assert(~a === (mask & ~_a).asUInt) - assert((a & b) === (_a & _b).asUInt) - assert((a | b) === (_a | _b).asUInt) - assert((a ^ b) === (_a ^ _b).asUInt) - assert((a.orR) === (_a != 0).asBool) - assert((a.andR) === (s"%${w}s".format(BigInt(_a).toString(2)).foldLeft(true)(_ && _ == '1')).asBool) - stop() -} - -class BitwiseOpsSpec extends ChiselPropSpec { - property("All bit-wise ops should return the correct result") { - forAll(safeUIntPair) { - case (w: Int, a: Int, b: Int) => - assertTesterPasses { new BitwiseOpsTester(w, a, b) } - } - } -} diff --git a/src/test/scala/chiselTests/BlackBox.scala b/src/test/scala/chiselTests/BlackBox.scala deleted file mode 100644 index f923a94a..00000000 --- a/src/test/scala/chiselTests/BlackBox.scala +++ /dev/null @@ -1,225 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.experimental._ -import chisel3.stage.ChiselStage -import chisel3.testers.{BasicTester, TesterDriver} -import chisel3.util._ - -class BlackBoxInverter extends BlackBox { - val io = IO(new Bundle() { - val in = Input(Bool()) - val out = Output(Bool()) - }) -} - -// 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()) - val out = Output(Bool()) - }) -} - -// Test Flip on top-level IO -class BlackBoxPassthrough2 extends BlackBox { - val io = IO(Flipped(new Bundle() { - val in = Output(Bool()) - val out = Input(Bool()) - })) -} - -class BlackBoxRegister extends BlackBox { - val io = IO(new Bundle() { - val clock = Input(Clock()) - val in = Input(Bool()) - val out = Output(Bool()) - }) -} - -class BlackBoxTester extends BasicTester { - val blackBoxPos = Module(new BlackBoxInverter) - val blackBoxNeg = Module(new BlackBoxInverter) - - blackBoxPos.io.in := 1.U - blackBoxNeg.io.in := 0.U - - assert(blackBoxNeg.io.out === 1.U) - assert(blackBoxPos.io.out === 0.U) - 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) - - blackBox.io.in := 1.U - assert(blackBox.io.out === 1.U) - stop() -} - -/** Instantiate multiple BlackBoxes with similar interfaces but different - * functionality. Used to detect failures in BlackBox naming and module - * deduplication. - */ - -class MultiBlackBoxTester extends BasicTester { - val blackBoxInvPos = Module(new BlackBoxInverter) - val blackBoxInvNeg = Module(new BlackBoxInverter) - val blackBoxPassPos = Module(new BlackBoxPassthrough) - val blackBoxPassNeg = Module(new BlackBoxPassthrough) - - blackBoxInvPos.io.in := 1.U - blackBoxInvNeg.io.in := 0.U - blackBoxPassPos.io.in := 1.U - blackBoxPassNeg.io.in := 0.U - - assert(blackBoxInvNeg.io.out === 1.U) - assert(blackBoxInvPos.io.out === 0.U) - assert(blackBoxPassNeg.io.out === 0.U) - assert(blackBoxPassPos.io.out === 1.U) - stop() -} - -class BlackBoxWithClockTester extends BasicTester { - val blackBox = Module(new BlackBoxRegister) - val model = Reg(Bool()) - - val (cycles, end) = Counter(true.B, 15) - - val impetus = cycles(0) - blackBox.io.clock := clock - blackBox.io.in := impetus - model := impetus - - when(cycles > 0.U) { - assert(blackBox.io.out === model) - } - when(end) { stop() } -} - -class BlackBoxConstant(value: Int) extends BlackBox(Map("VALUE" -> value, "WIDTH" -> log2Ceil(value + 1))) { - require(value >= 0, "value must be a UInt!") - val io = IO(new Bundle { - val out = Output(UInt(log2Ceil(value + 1).W)) - }) -} - -class BlackBoxStringParam(str: String) extends BlackBox(Map("STRING" -> str)) { - val io = IO(new Bundle { - val out = UInt(32.W) - }) -} - -class BlackBoxRealParam(dbl: Double) extends BlackBox(Map("REAL" -> dbl)) { - val io = IO(new Bundle { - val out = UInt(64.W) - }) -} - -class BlackBoxTypeParam(w: Int, raw: String) extends BlackBox(Map("T" -> RawParam(raw))) { - val io = IO(new Bundle { - val out = UInt(w.W) - }) -} - -class BlackBoxNoIO extends BlackBox { - // Whoops! typo - val ioo = IO(new Bundle { - val out = Output(UInt(8.W)) - }) -} - -class BlackBoxUIntIO extends BlackBox { - val io = IO(Output(UInt(8.W))) -} - -class BlackBoxWithParamsTester extends BasicTester { - val blackBoxOne = Module(new BlackBoxConstant(1)) - val blackBoxFour = Module(new BlackBoxConstant(4)) - val blackBoxStringParamOne = Module(new BlackBoxStringParam("one")) - val blackBoxStringParamTwo = Module(new BlackBoxStringParam("two")) - val blackBoxRealParamOne = Module(new BlackBoxRealParam(1.0)) - val blackBoxRealParamNeg = Module(new BlackBoxRealParam(-1.0)) - val blackBoxTypeParamBit = Module(new BlackBoxTypeParam(1, "bit")) - val blackBoxTypeParamWord = Module(new BlackBoxTypeParam(32, "bit [31:0]")) - - val (cycles, end) = Counter(true.B, 4) - - assert(blackBoxOne.io.out === 1.U) - assert(blackBoxFour.io.out === 4.U) - assert(blackBoxStringParamOne.io.out === 1.U) - assert(blackBoxStringParamTwo.io.out === 2.U) - assert(blackBoxRealParamOne.io.out === 0x3ff0000000000000L.U) - assert(blackBoxRealParamNeg.io.out === BigInt("bff0000000000000", 16).U) - assert(blackBoxTypeParamBit.io.out === 1.U) - assert(blackBoxTypeParamWord.io.out === "hdeadbeef".U(32.W)) - - when(end) { stop() } -} - -class BlackBoxSpec extends ChiselFlatSpec { - "A BlackBoxed inverter" should "work" in { - assertTesterPasses({ new BlackBoxTester }, Seq("/chisel3/BlackBoxTest.v"), TesterDriver.verilatorOnly) - } - "A BlackBoxed with flipped IO" should "work" in { - assertTesterPasses({ new BlackBoxFlipTester }, Seq("/chisel3/BlackBoxTest.v"), TesterDriver.verilatorOnly) - } - "Multiple BlackBoxes" should "work" in { - assertTesterPasses({ new MultiBlackBoxTester }, Seq("/chisel3/BlackBoxTest.v"), TesterDriver.verilatorOnly) - } - "A BlackBoxed register" should "work" in { - assertTesterPasses({ new BlackBoxWithClockTester }, Seq("/chisel3/BlackBoxTest.v"), TesterDriver.verilatorOnly) - } - "BlackBoxes with parameters" should "work" in { - assertTesterPasses({ new BlackBoxWithParamsTester }, Seq("/chisel3/BlackBoxTest.v"), TesterDriver.verilatorOnly) - } - "DataMirror.modulePorts" should "work with BlackBox" in { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle {}) - val m = Module(new BlackBoxPassthrough) - assert(DataMirror.modulePorts(m) == Seq("in" -> m.io.in, "out" -> m.io.out)) - }) - } - "A BlackBox using suggestName(\"io\")" should "work (but don't do this)" in { - assertTesterPasses({ new BlackBoxTesterSuggestName }, Seq("/chisel3/BlackBoxTest.v"), TesterDriver.verilatorOnly) - } - - "A BlackBox with no 'val io'" should "give a reasonable error message" in { - (the[ChiselException] thrownBy { - ChiselStage.elaborate(new Module { - val inst = Module(new BlackBoxNoIO) - }) - }).getMessage should include("must have a port named 'io' of type Record") - } - - "A BlackBox with non-Record 'val io'" should "give a reasonable error message" in { - (the[ChiselException] thrownBy { - ChiselStage.elaborate(new Module { - val inst = Module(new BlackBoxUIntIO) - }) - }).getMessage should include("must have a port named 'io' of type Record") - } -} diff --git a/src/test/scala/chiselTests/BlackBoxImpl.scala b/src/test/scala/chiselTests/BlackBoxImpl.scala deleted file mode 100644 index 4cc72dd0..00000000 --- a/src/test/scala/chiselTests/BlackBoxImpl.scala +++ /dev/null @@ -1,139 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import java.io.File - -import chisel3._ -import chisel3.util.{HasBlackBoxInline, HasBlackBoxPath, HasBlackBoxResource} -import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} -import firrtl.transforms.BlackBoxNotFoundException -import org.scalacheck.Test.Failed -import org.scalatest.Succeeded -import org.scalatest.freespec.AnyFreeSpec -import org.scalatest.matchers.should.Matchers - -class BlackBoxAdd(n: Int) extends HasBlackBoxInline { - val io = IO(new Bundle { - val in = Input(UInt(16.W)) - val out = Output(UInt(16.W)) - }) - - setInline( - "BlackBoxAdd.v", - s""" - |module BlackBoxAdd( - | input [15:0] in, - | output [15:0] out - |); - | assign out = in + $n; - |endmodule - """.stripMargin - ) -} - -class UsesBlackBoxAddViaInline extends Module { - val io = IO(new Bundle { - val in = Input(UInt(16.W)) - val out = Output(UInt(16.W)) - }) - - val blackBoxAdd = Module(new BlackBoxAdd(5)) - blackBoxAdd.io.in := io.in - io.out := blackBoxAdd.io.out -} - -class BlackBoxMinus extends HasBlackBoxResource { - val io = IO(new Bundle { - val in1 = Input(UInt(16.W)) - val in2 = Input(UInt(16.W)) - val out = Output(UInt(16.W)) - }) - addResource("/chisel3/BlackBoxTest.v") -} - -class BlackBoxMinusPath extends HasBlackBoxPath { - val io = IO(new Bundle { - val in1 = Input(UInt(16.W)) - val in2 = Input(UInt(16.W)) - val out = Output(UInt(16.W)) - }) - addPath(new File("src/test/resources/chisel3/BlackBoxTest.v").getCanonicalPath) -} - -class UsesBlackBoxMinusViaResource extends Module { - val io = IO(new Bundle { - val in1 = Input(UInt(16.W)) - val in2 = Input(UInt(16.W)) - val out = Output(UInt(16.W)) - }) - - val mod0 = Module(new BlackBoxMinus) - - mod0.io.in1 := io.in1 - mod0.io.in2 := io.in2 - io.out := mod0.io.out -} - -class UsesBlackBoxMinusViaPath extends Module { - val io = IO(new Bundle { - val in1 = Input(UInt(16.W)) - val in2 = Input(UInt(16.W)) - val out = Output(UInt(16.W)) - }) - - val mod0 = Module(new BlackBoxMinusPath) - - mod0.io.in1 := io.in1 - mod0.io.in2 := io.in2 - io.out := mod0.io.out -} - -class BlackBoxResourceNotFound extends HasBlackBoxResource { - val io = IO(new Bundle {}) - addResource("/missing.resource") -} - -class UsesMissingBlackBoxResource extends RawModule { - val foo = Module(new BlackBoxResourceNotFound) -} - -class BlackBoxImplSpec extends AnyFreeSpec with Matchers { - val targetDir = "test_run_dir" - val stage = new ChiselStage - "BlackBox can have verilator source implementation" - { - "Implementations can be contained in-line" in { - stage.execute( - Array("-X", "verilog", "--target-dir", targetDir), - Seq(ChiselGeneratorAnnotation(() => new UsesBlackBoxAddViaInline)) - ) - val verilogOutput = new File(targetDir, "BlackBoxAdd.v") - verilogOutput.exists() should be(true) - verilogOutput.delete() - } - "Implementations can be contained in resource files" in { - stage.execute( - Array("-X", "low", "--target-dir", targetDir), - Seq(ChiselGeneratorAnnotation(() => new UsesBlackBoxMinusViaResource)) - ) - val verilogOutput = new File(targetDir, "BlackBoxTest.v") - verilogOutput.exists() should be(true) - verilogOutput.delete() - } - "Implementations can be contained in arbitrary files" in { - stage.execute( - Array("-X", "low", "--target-dir", targetDir), - Seq(ChiselGeneratorAnnotation(() => new UsesBlackBoxMinusViaPath)) - ) - val verilogOutput = new File(targetDir, "BlackBoxTest.v") - verilogOutput.exists() should be(true) - verilogOutput.delete() - Succeeded - } - "Resource files that do not exist produce Chisel errors" in { - assertThrows[BlackBoxNotFoundException] { - ChiselStage.emitChirrtl(new UsesMissingBlackBoxResource) - } - } - } -} diff --git a/src/test/scala/chiselTests/BoringUtilsSpec.scala b/src/test/scala/chiselTests/BoringUtilsSpec.scala deleted file mode 100644 index 9be2d75a..00000000 --- a/src/test/scala/chiselTests/BoringUtilsSpec.scala +++ /dev/null @@ -1,135 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.util.Counter -import chisel3.testers._ -import chisel3.experimental.{BaseModule, ChiselAnnotation, RunFirrtlTransform} -import chisel3.util.experimental.BoringUtils - -import firrtl.{ChirrtlForm, CircuitForm, CircuitState, DependencyAPIMigration, Transform} -import firrtl.annotations.{Annotation, NoTargetAnnotation} -import firrtl.options.Dependency -import firrtl.transforms.{DontTouchAnnotation, NoDedupAnnotation} -import firrtl.passes.wiring.{WiringException, WiringTransform} -import firrtl.stage.Forms - -abstract class ShouldntAssertTester(cyclesToWait: BigInt = 4) extends BasicTester { - val dut: BaseModule - val (_, done) = Counter(true.B, 2) - when(done) { stop() } -} - -class StripNoDedupAnnotation extends Transform with DependencyAPIMigration { - override def prerequisites = Forms.ChirrtlForm - override def optionalPrerequisites = Seq.empty - override def optionalPrerequisiteOf = Dependency[WiringTransform] +: Forms.ChirrtlEmitters - override def invalidates(a: Transform) = false - def execute(state: CircuitState): CircuitState = { - state.copy(annotations = state.annotations.filter { case _: NoDedupAnnotation => false; case _ => true }) - } -} - -class BoringUtilsSpec extends ChiselFlatSpec with ChiselRunners { - - class BoringInverter extends Module { - val io = IO(new Bundle {}) - val a = Wire(UInt(1.W)) - val notA = Wire(UInt(1.W)) - val b = Wire(UInt(1.W)) - a := 0.U - notA := ~a - b := a - chisel3.assert(b === 1.U) - BoringUtils.addSource(notA, "x") - BoringUtils.addSink(b, "x") - } - - behavior.of("BoringUtils.{addSink, addSource}") - - it should "connect two wires within a module" in { - runTester( - new ShouldntAssertTester { val dut = Module(new BoringInverter) }, - annotations = TesterDriver.verilatorOnly - ) should be(true) - } - - trait WireX { this: BaseModule => - val x = Wire(UInt(4.W)) - chisel3.experimental.annotate(new ChiselAnnotation { - def toFirrtl: Annotation = DontTouchAnnotation(x.toNamed) - }) - } - - class Source extends RawModule with WireX { - val in = IO(Input(UInt())) - x := in - } - - class Sink extends RawModule with WireX { - val out = IO(Output(UInt())) - x := 0.U // Default value. Output is zero unless we bore... - out := x - } - - 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)) - - /* Sources are differentiated by their input connections only. */ - sources.zip(Seq(0, 1, 2)).map { case (a, b) => a.in := b.U } - - /* Sinks are differentiated by their post-boring outputs. */ - sinks.zip(Seq(0, 1, 1, 2, 2, 2)).map { case (a, b) => chisel3.assert(a.out === b.U) } - } - - /** This is testing a complicated wiring pattern and exercising - * the necessity of disabling deduplication for sources and sinks. - * Without disabling deduplication, this test will fail. - */ - class TopTester extends ShouldntAssertTester { - val dut = Module(new Top(4)) - BoringUtils.bore(dut.sources(1).x, Seq(dut.sinks(1).x, dut.sinks(2).x)) - BoringUtils.bore(dut.sources(2).x, Seq(dut.sinks(3).x, dut.sinks(4).x, dut.sinks(5).x)) - } - - trait FailViaDedup { this: TopTester => - case object FooAnnotation extends NoTargetAnnotation - chisel3.experimental.annotate(new ChiselAnnotation with RunFirrtlTransform { - def toFirrtl: Annotation = FooAnnotation - def transformClass: Class[_ <: Transform] = classOf[StripNoDedupAnnotation] - }) - } - - behavior.of("BoringUtils.bore") - - it should "connect across modules using BoringUtils.bore" in { - runTester(new TopTester, annotations = TesterDriver.verilatorOnly) should be(true) - } - - it should "throw an exception if NoDedupAnnotations are removed" in { - intercept[WiringException] { - runTester(new TopTester with FailViaDedup, annotations = Seq(TesterDriver.VerilatorBackend)) - }.getMessage should startWith("Unable to determine source mapping for sink") - } - - class InternalBore extends RawModule { - val in = IO(Input(Bool())) - val out = IO(Output(Bool())) - out := false.B - BoringUtils.bore(in, Seq(out)) - } - - class InternalBoreTester extends ShouldntAssertTester { - val dut = Module(new InternalBore) - dut.in := true.B - chisel3.assert(dut.out === true.B) - } - - it should "work for an internal (same module) BoringUtils.bore" in { - runTester(new InternalBoreTester, annotations = TesterDriver.verilatorOnly) should be(true) - } - -} diff --git a/src/test/scala/chiselTests/BulkConnectSpec.scala b/src/test/scala/chiselTests/BulkConnectSpec.scala deleted file mode 100644 index 0a1616d3..00000000 --- a/src/test/scala/chiselTests/BulkConnectSpec.scala +++ /dev/null @@ -1,139 +0,0 @@ -package chiselTests - -import chisel3._ -import chisel3.util.Decoupled -import chisel3.stage.ChiselStage -import chisel3.testers.BasicTester - -class BulkConnectSpec extends ChiselPropSpec { - property("Chisel connects should emit FIRRTL bulk connects when possible") { - val chirrtl = ChiselStage.emitChirrtl(new Module { - val io = IO(new Bundle { - val inMono = Input(Vec(4, UInt(8.W))) - val outMono = Output(Vec(4, UInt(8.W))) - val inBi = Input(Vec(4, UInt(8.W))) - val outBi = Output(Vec(4, UInt(8.W))) - }) - io.outMono := io.inMono - io.outBi <> io.inBi - }) - chirrtl should include("io.outMono <= io.inMono") - chirrtl should include("io.outBi <= io.inBi") - } - - property("Chisel connects should not emit FIRRTL bulk connects for Stringly-typed connections") { - object Foo { - import Chisel._ - // Chisel._ bundle - class BundleParent extends Bundle { - val foo = UInt(width = 8) - } - class BundleChild extends BundleParent { - val bar = UInt(width = 8) - } - } - - import Foo._ - - // chisel3._ bundle - class MyBundle(child: Boolean) extends Bundle { - val fizz = UInt(8.W) - val buzz = if (child) new BundleChild else new BundleParent - } - - val chirrtl = ChiselStage.emitChirrtl(new Module { - // Checking MonoConnect - val in = IO(Input(new MyBundle(true))) - val out = IO(Output(new MyBundle(false))) - out := in - - // Checking BulkConnect (with Decoupled) - val enq = IO(Flipped(Decoupled(new BundleChild))) - val deq = IO(Decoupled(new BundleParent)) - deq <> enq - }) - - chirrtl should include("out.buzz.foo <= in.buzz.foo") - chirrtl should include("out.fizz <= in.fizz") - chirrtl should include("deq.bits <- enq.bits") - chirrtl should include("deq.valid <= enq.valid") - chirrtl should include("enq.ready <= deq.ready") - - chirrtl shouldNot include("deq <= enq") - chirrtl shouldNot include("deq.bits.foo <= enq.bits.foo") - chirrtl shouldNot include("deq.bits.foo <- enq.bits.foo") - chirrtl shouldNot include("deq.bits.bar") - } - - property("Chisel connects should not emit FIRRTL bulk connects between differing FIRRTL types") { - val chirrtl = ChiselStage.emitChirrtl(new Module { - val in = IO(Flipped(new Bundle { - val foo = Flipped(new Bundle { - val bar = Input(UInt(8.W)) - }) - })) - val out = IO(Output(new Bundle { - val foo = new Bundle { - val bar = UInt(8.W) - } - })) - // Both of these connections are legal in Chisel, but in and out do not have the same type - out := in - out <> in - }) - // out <- in is illegal FIRRTL - exactly(2, chirrtl.split('\n')) should include("out.foo.bar <= in.foo.bar") - chirrtl shouldNot include("out <= in") - chirrtl shouldNot include("out <- in") - } - - property("Chisel connects should not emit a FIRRTL bulk connect for a bidirectional MonoConnect") { - val chirrtl = ChiselStage.emitChirrtl(new Module { - val enq = IO(Flipped(Decoupled(UInt(8.W)))) - val deq = IO(Decoupled(UInt(8.W))) - - // Implicitly create a MonoConnect from enq to a wire - // enq is a Decoupled and so has input/output signals - // We should not bulk connect in this case - val wire = WireDefault(enq) - dontTouch(wire) - deq <> enq - }) - - chirrtl shouldNot include("wire <= enq") - chirrtl should include("wire.bits <= enq.bits") - chirrtl should include("wire.valid <= enq.valid") - chirrtl should include("wire.ready <= enq.ready") - chirrtl should include("deq <= enq") - } - - property("Chisel connects should not emit a FIRRTL bulk connect for BlackBox IO Bundles") { - class MyBundle extends Bundle { - val O: Bool = Output(Bool()) - val I: Bool = Input(Bool()) - } - - val chirrtl = ChiselStage.emitChirrtl(new Module { - val io: MyBundle = IO(Flipped(new MyBundle)) - - val bb = Module(new BlackBox { - val io: MyBundle = IO(Flipped(new MyBundle)) - }) - - io <> bb.io - }) - // There won't be a bb.io Bundle in FIRRTL, so connections have to be done element-wise - chirrtl should include("bb.O <= io.O") - chirrtl should include("io.I <= bb.I") - } - - property("MonoConnect should bulk connect undirectioned internal wires") { - val chirrtl = ChiselStage.emitChirrtl(new Module { - val io = IO(new Bundle {}) - val w1 = Wire(Vec(2, UInt(8.W))) - val w2 = Wire(Vec(2, UInt(8.W))) - w2 := w1 - }) - chirrtl should include("w2 <= w1") - } -} diff --git a/src/test/scala/chiselTests/BundleElementsSpec.scala b/src/test/scala/chiselTests/BundleElementsSpec.scala deleted file mode 100644 index afca3d81..00000000 --- a/src/test/scala/chiselTests/BundleElementsSpec.scala +++ /dev/null @@ -1,564 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.experimental.FixedPoint -import chisel3.stage.ChiselStage -import chisel3.util.Decoupled -import org.scalatest.exceptions.TestFailedException -import org.scalatest.freespec.AnyFreeSpec -import org.scalatest.matchers.should.Matchers - -import scala.language.reflectiveCalls - -/* Rich and complicated bundle examples - */ -trait BpipSuperTraitWithField { - val bpipSuperTraitGood = SInt(17.W) - def bpipSuperTraitBad = SInt(22.W) -} - -trait BpipTraitWithField extends BpipSuperTraitWithField { - val bpipTraitGood = SInt(17.W) - def bpipTraitBad = SInt(22.W) -} - -class BpipOneField extends Bundle with BpipTraitWithField { - val bpipOneFieldOne = SInt(8.W) - val bpipOneFieldTwo = SInt(8.W) -} - -class BpipTwoField extends BpipOneField { - val bpipTwoFieldOne = SInt(8.W) - val bpipTwoFieldTwo = Vec(4, UInt(12.W)) - val myInt = 7 - val baz = Decoupled(UInt(16.W)) -} - -class BpipDecoupled extends BpipOneField { - val bpipDecoupledSInt = SInt(8.W) - val bpipDecoupledVec = Vec(4, UInt(12.W)) - val bpipDecoupledDecoupled = Decoupled(UInt(16.W)) -} - -class HasDecoupledBundleByInheritance extends Module { - val out1 = IO(Output(new BpipDecoupled)) - assertElementsMatchExpected(out1)( - "bpipDecoupledDecoupled" -> _.bpipDecoupledDecoupled, - "bpipDecoupledVec" -> _.bpipDecoupledVec, - "bpipDecoupledSInt" -> _.bpipDecoupledSInt, - "bpipOneFieldTwo" -> _.bpipOneFieldTwo, - "bpipOneFieldOne" -> _.bpipOneFieldOne, - "bpipTraitGood" -> _.bpipTraitGood, - "bpipSuperTraitGood" -> _.bpipSuperTraitGood - ) -} - -/* plugin should not affect the seq detection */ -class DebugProblem3 extends Module { - val out1 = IO(Output(new BpipTwoField)) - assertElementsMatchExpected(out1)( - "baz" -> _.baz, - "bpipTwoFieldTwo" -> _.bpipTwoFieldTwo, - "bpipTwoFieldOne" -> _.bpipTwoFieldOne, - "bpipOneFieldTwo" -> _.bpipOneFieldTwo, - "bpipOneFieldOne" -> _.bpipOneFieldOne, - "bpipTraitGood" -> _.bpipTraitGood, - "bpipSuperTraitGood" -> _.bpipSuperTraitGood - ) -} - -class BpipBadSeqBundle extends Bundle { - val bpipBadSeqBundleGood = UInt(999.W) - val bpipBadSeqBundleBad = Seq(UInt(16.W), UInt(8.W), UInt(4.W)) -} - -class HasBadSeqBundle extends Module { - val out1 = IO(Output(new BpipBadSeqBundle)) -} - -class BpipBadSeqBundleWithIgnore extends Bundle with IgnoreSeqInBundle { - val goodFieldWithIgnore = UInt(999.W) - val badSeqFieldWithIgnore = Seq(UInt(16.W), UInt(8.W), UInt(4.W)) -} - -class UsesIgnoreSeqInBundle extends Module { - val out1 = IO(Output(new BpipBadSeqBundleWithIgnore)) -} - -/* This is mostly a test of the field order */ -class BpipP8_1 extends Bundle { - val field_1_1 = UInt(11.W) - val field_1_2 = UInt(12.W) -} - -class BpipP8_2 extends BpipP8_1 { - val field_2_1 = UInt(11.W) - val field_2_2 = UInt(12.W) -} - -class BpipP8_3 extends BpipP8_2 { - val field_3_1 = UInt(11.W) - val field_3_2 = UInt(12.W) -} - -/* plugin should not affect the seq detection */ -class ForFieldOrderingTest extends Module { - val out1 = IO(Output(new BpipP8_3)) - out1 := DontCare - assertElementsMatchExpected(out1)( - "field_3_2" -> _.field_3_2, - "field_3_1" -> _.field_3_1, - "field_2_2" -> _.field_2_2, - "field_2_1" -> _.field_2_1, - "field_1_2" -> _.field_1_2, - "field_1_1" -> _.field_1_1 - ) -} - -/* plugin should allow parameter var fields */ -class HasValParamsToBundle extends Module { - // The following block does not work, suggesting that ParamIsField is not a case we need to solve - class BpipParamIsField0(val paramField0: UInt) extends Bundle - class BpipParamIsField1(val paramField1: UInt) extends BpipParamIsField0(UInt(66.W)) - - val out3 = IO(Output(new BpipParamIsField1(UInt(10.W)))) - val out4 = IO(Output(new BpipParamIsField1(UInt(10.W)))) - out3 := DontCare - assertElementsMatchExpected(out3)("paramField0" -> _.paramField0, "paramField1" -> _.paramField1) - assertElementsMatchExpected(out4)("paramField0" -> _.paramField0, "paramField1" -> _.paramField1) -} - -class HasGenParamsPassedToSuperclasses extends Module { - - class OtherBundle extends Bundle { - val otherField = UInt(55.W) - } - - class BpipWithGen[T <: Data, TT <: Data](gen: T, gen2: => TT) extends Bundle { - val superFoo = gen - val superQux = gen2 - } - -// class BpipDemoBundle[T <: Data](gen: T, gen2: => T) extends BpipTwoField with BpipVarmint { - class BpipUsesWithGen[T <: Data](gen: T, gen2: => T) extends BpipWithGen(gen, gen2) { - // val foo = gen - val bar = Bool() - val qux = gen2 - val bad = 444 - val baz = Decoupled(UInt(16.W)) - } - - val out1 = IO(Output(new BpipUsesWithGen(UInt(4.W), new OtherBundle))) - val out2 = IO(Output(new BpipUsesWithGen(UInt(4.W), FixedPoint(10.W, 4.BP)))) - - out1 := DontCare - - assertElementsMatchExpected(out1)( - "baz" -> _.baz, - "qux" -> _.qux, - "bar" -> _.bar, - "superQux" -> _.superQux, - "superFoo" -> _.superFoo - ) - assertElementsMatchExpected(out2)( - "baz" -> _.baz, - "qux" -> _.qux, - "bar" -> _.bar, - "superQux" -> _.superQux, - "superFoo" -> _.superFoo - ) -} - -/* Testing whether gen fields superFoo and superQux can be found when they are - * declared in a superclass - * - */ -class UsesGenFiedldsInSuperClass extends Module { - class BpipWithGen[T <: Data](gen: T) extends Bundle { - val superFoo = gen - val superQux = gen - } - - class BpipUsesWithGen[T <: Data](gen: T) extends BpipWithGen(gen) {} - - val out = IO(Output(new BpipUsesWithGen(UInt(4.W)))) - - out := DontCare - - assertElementsMatchExpected(out)() -} - -/* Testing whether gen fields superFoo and superQux can be found when they are - * declared in a superclass - * - */ -class BpipBadBundleWithHardware extends Bundle { - val bpipWithHardwareGood = UInt(8.W) - val bpipWithHardwareBad = 244.U(16.W) -} - -class HasHardwareFieldsInBundle extends Module { - val out = IO(Output(new BpipBadBundleWithHardware)) - assertElementsMatchExpected(out)() -} - -/* This is legal because of => - */ -class UsesBundleWithGeneratorField extends Module { - class BpipWithGen[T <: Data](gen: => T) extends Bundle { - val superFoo = gen - val superQux = gen - } - - class BpipUsesWithGen[T <: Data](gen: => T) extends BpipWithGen(gen) - - val out = IO(Output(new BpipUsesWithGen(UInt(4.W)))) - - out := DontCare - - assertElementsMatchExpected(out)("superQux" -> _.superQux, "superFoo" -> _.superFoo) -} - -/* Testing whether gen fields superFoo and superQux can be found when they are - * declared in a superclass - * - */ -class BundleElementsSpec extends AnyFreeSpec with Matchers { - - /** Tests a whole bunch of different Bundle constructions - */ - class BpipIsComplexBundle extends Module { - - trait BpipVarmint { - val varmint = Bool() - - def vermin = Bool() - - private val puppy = Bool() - } - - abstract class BpipAbstractBundle extends Bundle { - def doNothing: Unit - - val fromAbstractBundle = UInt(22.W) - } - - class BpipOneField extends Bundle { - val fieldOne = SInt(8.W) - } - - class BpipTwoField extends BpipOneField { - val fieldTwo = SInt(8.W) - val fieldThree = Vec(4, UInt(12.W)) - } - - class BpipAnimalBundle(w1: Int, w2: Int) extends Bundle { - val dog = SInt(w1.W) - val fox = UInt(w2.W) - } - - class BpipDemoBundle[T <: Data](gen: T, gen2: => T) extends BpipTwoField with BpipVarmint { - val foo = gen - val bar = Bool() - val qux = gen2 - val bad = 44 - val baz = Decoupled(UInt(16.W)) - val animals = new BpipAnimalBundle(4, 8) - } - - val out = IO(Output(new BpipDemoBundle(UInt(4.W), FixedPoint(10.W, 4.BP)))) - - val out2 = IO(Output(new BpipAbstractBundle { - override def doNothing: Unit = () - - val notAbstract: Bool = Bool() - })) - - val out4 = IO(Output(new BpipAnimalBundle(99, 100))) - val out5 = IO(Output(new BpipTwoField)) - - out := DontCare - out5 := DontCare - - assertElementsMatchExpected(out)( - "animals" -> _.animals, - "baz" -> _.baz, - "qux" -> _.qux, - "bar" -> _.bar, - "varmint" -> _.varmint, - "fieldThree" -> _.fieldThree, - "fieldTwo" -> _.fieldTwo, - "fieldOne" -> _.fieldOne, - "foo" -> _.foo - ) - assertElementsMatchExpected(out5)("fieldThree" -> _.fieldThree, "fieldTwo" -> _.fieldTwo, "fieldOne" -> _.fieldOne) - assertElementsMatchExpected(out2)("notAbstract" -> _.notAbstract, "fromAbstractBundle" -> _.fromAbstractBundle) - assertElementsMatchExpected(out4)("fox" -> _.fox, "dog" -> _.dog) - } - - "Complex Bundle with inheritance, traits and params. DebugProblem1" in { - ChiselStage.emitFirrtl(new BpipIsComplexBundle) - } - - "Decoupled Bundle with inheritance" in { - ChiselStage.emitFirrtl(new HasDecoupledBundleByInheritance) - } - - "Simple bundle inheritance. DebugProblem3" in { - ChiselStage.emitFirrtl(new DebugProblem3) - } - - "Bundles containing Seq[Data] should be compile erorr. HasBadSeqBundle" in { - intercept[ChiselException] { - ChiselStage.emitFirrtl(new HasBadSeqBundle) - } - } - - "IgnoreSeqInBundle allows Seq[Data] in bundle" in { - ChiselStage.emitFirrtl(new UsesIgnoreSeqInBundle) - } - - "Simple field ordering test." in { - ChiselStage.emitFirrtl(new ForFieldOrderingTest) - } - - "Val params to Bundle should be an Exception." in { - ChiselStage.emitFirrtl(new HasValParamsToBundle) - } - - "Should handle gen params passed to superclasses" in { - ChiselStage.emitFirrtl(new HasGenParamsPassedToSuperclasses) - } - - "Aliased fields should be detected and throw an exception, because gen: Data, with no =>" in { - intercept[AliasedAggregateFieldException] { - ChiselStage.emitFirrtl(new UsesGenFiedldsInSuperClass) - } - } - - "Error when bundle fields are hardware, such as literal values. HasHardwareFieldsInBundle" in { - val e = intercept[ExpectedChiselTypeException] { - ChiselStage.emitFirrtl(new HasHardwareFieldsInBundle) - } - e.getMessage should include( - "Bundle: BpipBadBundleWithHardware contains hardware fields: bpipWithHardwareBad: UInt<16>(244)" - ) - } - - "Aliased fields not created when using gen: => Data" in { - ChiselStage.emitFirrtl(new UsesBundleWithGeneratorField) - } - - class OptionBundle(val hasIn: Boolean) extends Bundle { - val in = if (hasIn) { - Some(Input(Bool())) - } else { - None - } - val out = Output(Bool()) - } - - class UsesBundleWithOptionFields extends Module { - val outTrue = IO(Output(new OptionBundle(hasIn = true))) - val outFalse = IO(Output(new OptionBundle(hasIn = false))) - //NOTE: The _.in.get _.in is an optional field - assertElementsMatchExpected(outTrue)("out" -> _.out, "in" -> _.in.get) - assertElementsMatchExpected(outFalse)("out" -> _.out) - } - - "plugin should work with Bundles with Option fields" in { - ChiselStage.emitFirrtl(new UsesBundleWithOptionFields) - } - - "plugin should work with enums in bundles" in { - object Enum0 extends ChiselEnum { - val s0, s1, s2 = Value - } - - ChiselStage.emitFirrtl(new Module { - val out = IO(Output(new Bundle { - val a = UInt(8.W) - val b = Bool() - val c = Enum0.Type - })) - assertElementsMatchExpected(out)("b" -> _.b, "a" -> _.a) - }) - } - - "plugin will NOT see fields that are Data but declared in some way as Any" in { - //This is not incompatible with chisel not using the plugin, but this code is considered bad practice - - ChiselStage.emitFirrtl(new Module { - val out = IO(Output(new Bundle { - val a = UInt(8.W) - val b: Any = Bool() - })) - - intercept[TestFailedException] { - assert(out.elements.keys.exists(_ == "b")) - } - }) - } - - "plugin tests should fail properly in the following cases" - { - - class BundleAB extends Bundle { - val a = Output(UInt(8.W)) - val b = Output(Bool()) - } - - def checkAssertion(checks: (BundleAB => (String, Data))*)(expectedMessage: String): Unit = { - intercept[AssertionError] { - ChiselStage.emitFirrtl(new Module { - val out = IO(new BundleAB) - assertElementsMatchExpected(out)(checks: _*) - }) - }.getMessage should include(expectedMessage) - } - - "one of the expected data values is wrong" in { - checkAssertion("b" -> _.b, "a" -> _.b)("field 'a' data field BundleElementsSpec_Anon.out.a") - } - - "one of the expected field names in wrong" in { - checkAssertion("b" -> _.b, "z" -> _.a)("field: 'a' did not match expected 'z'") - } - - "fields that are expected are not returned by the elements method" in { - checkAssertion("b" -> _.b, "a" -> _.a, "c" -> _.a)("#elements is missing the 'c' field") - } - - "fields returned by the element are not specified in the expected fields" in { - checkAssertion("b" -> _.b)("expected fields did not include 'a' field found in #elements") - } - - "multiple errors between elements method and expected fields are shown in the assertion error message" in { - checkAssertion()( - "expected fields did not include 'b' field found in #elements," + - " expected fields did not include 'a' field found in #elements" - ) - } - } - - "plugin should error correctly when bundles contain only a Option field" in { - ChiselStage.emitFirrtl(new Module { - val io = IO(new Bundle { - val foo = Input(UInt(8.W)) - val x = new Bundle { - val y = if (false) Some(Input(UInt(8.W))) else None - } - }) - assertElementsMatchExpected(io)("x" -> _.x, "foo" -> _.foo) - assertElementsMatchExpected(io.x)() - }) - } - - "plugin should handle fields using the boolean to option construct" in { - case class ALUConfig( - xLen: Int, - mul: Boolean, - b: Boolean) - - class OptionalBundle extends Bundle { - val optionBundleA = Input(UInt(3.W)) - val optionBundleB = Input(UInt(7.W)) - } - - class ALU(c: ALUConfig) extends Module { - - class BpipOptionBundle extends Bundle with IgnoreSeqInBundle { - val bpipUIntVal = Input(UInt(8.W)) - lazy val bpipUIntLazyVal = Input(UInt(8.W)) - var bpipUIntVar = Input(UInt(8.W)) - - def bpipUIntDef = Input(UInt(8.W)) - - val bpipOptionUInt = Some(Input(UInt(16.W))) - val bpipOptionOfBundle = if (c.b) Some(new OptionalBundle) else None - val bpipSeqData = Seq(UInt(8.W), UInt(8.W)) - } - - val io = IO(new BpipOptionBundle) - assertElementsMatchExpected(io)( - "bpipUIntLazyVal" -> _.bpipUIntLazyVal, - "bpipOptionUInt" -> _.bpipOptionUInt.get, - "bpipUIntVar" -> _.bpipUIntVar, - "bpipUIntVal" -> _.bpipUIntVal - ) - } - - ChiselStage.emitFirrtl(new ALU(ALUConfig(10, mul = true, b = false))) - } - - "TraceSpec test, different version found in TraceSpec.scala" in { - class Bundle0 extends Bundle { - val a = UInt(8.W) - val b = Bool() - val c = Enum0.Type - } - - class Bundle1 extends Bundle { - val a = new Bundle0 - val b = Vec(4, Vec(4, Bool())) - } - - class Module0 extends Module { - val i = IO(Input(new Bundle1)) - val o = IO(Output(new Bundle1)) - val r = Reg(new Bundle1) - o := r - r := i - - assertElementsMatchExpected(i)("b" -> _.b, "a" -> _.a) - assertElementsMatchExpected(o)("b" -> _.b, "a" -> _.a) - assertElementsMatchExpected(r)("b" -> _.b, "a" -> _.a) - } - - class Module1 extends Module { - val i = IO(Input(new Bundle1)) - val m0 = Module(new Module0) - m0.i := i - m0.o := DontCare - assertElementsMatchExpected(i)("b" -> _.b, "a" -> _.a) - } - - object Enum0 extends ChiselEnum { - val s0, s1, s2 = Value - } - - ChiselStage.emitFirrtl(new Module1) - } -} -/* Checks that the elements method of a bundle matches the testers idea of what the bundle field names and their - * associated data match and that they have the same number of fields in the same order - */ -object assertElementsMatchExpected { - def apply[T <: Bundle](bun: T)(checks: (T => (String, Data))*): Unit = { - val expected = checks.map { fn => fn(bun) } - val elements = bun.elements - val missingMsg = "missing field in #elements" - val extraMsg = "extra field in #elements" - val paired = elements.toSeq.zipAll(expected, missingMsg -> UInt(1.W), extraMsg -> UInt(1.W)) - val errorsStrings = paired.flatMap { - case (element, expected) => - val (elementName, elementData) = element - val (expectedName, expectedData) = expected - if (elementName == missingMsg) { - Some(s"#elements is missing the '$expectedName' field") - } else if (expectedName == extraMsg) { - Some(s"expected fields did not include '$elementName' field found in #elements") - } else if (elementName != expectedName) { - Some(s"field: '$elementName' did not match expected '$expectedName'") - } else if (elementData != expectedData) { - Some( - s"field '$elementName' data field ${elementData}(${elementData.hashCode}) did not match expected $expectedData(${expectedData.hashCode})" - ) - } else { - None - } - } - assert(errorsStrings.isEmpty, s"Bundle: ${bun.getClass.getName}: " + errorsStrings.mkString(", ")) - } -} diff --git a/src/test/scala/chiselTests/BundleLiteralSpec.scala b/src/test/scala/chiselTests/BundleLiteralSpec.scala deleted file mode 100644 index f90e230d..00000000 --- a/src/test/scala/chiselTests/BundleLiteralSpec.scala +++ /dev/null @@ -1,356 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.testers.BasicTester -import chisel3.experimental.BundleLiterals._ -import chisel3.experimental.VecLiterals.AddVecLiteralConstructor -import chisel3.experimental.{BundleLiteralException, ChiselRange, FixedPoint, Interval} - -class BundleLiteralSpec extends ChiselFlatSpec with Utils { - object MyEnum extends ChiselEnum { - val sA, sB = Value - } - object MyEnumB extends ChiselEnum { - val sA, sB = Value - } - class MyBundle extends Bundle { - val a = UInt(8.W) - val b = Bool() - val c = MyEnum() - } - - class LongBundle extends Bundle { - val a = UInt(48.W) - val b = SInt(32.W) - val c = FixedPoint(16.W, 4.BP) - } - - "bundle literals" should "pack" in { - assertTesterPasses { - new BasicTester { - val bundleLit = (new MyBundle).Lit(_.a -> 42.U, _.b -> false.B, _.c -> MyEnum.sB) - bundleLit.litOption should equal(Some(169)) // packed as 42 (8-bit), false=0 (1-bit), sB=1 (1-bit) - chisel3.assert(bundleLit.asUInt() === bundleLit.litOption.get.U) // sanity-check consistency with runtime - - val longBundleLit = - (new LongBundle).Lit(_.a -> 0xdeaddeadbeefL.U, _.b -> (-0x0beef00dL).S(32.W), _.c -> 4.5.F(16.W, 4.BP)) - longBundleLit.litOption should equal( - Some( - (BigInt(0xdeaddeadbeefL) << 48) - + (BigInt(0xffffffffL - 0xbeef00dL + 1) << 16) - + BigInt(72) - ) - ) - chisel3.assert(longBundleLit.asUInt() === longBundleLit.litOption.get.U) - - stop() - } - } - } - - "bundle literals" should "work in RTL" in { - val outsideBundleLit = (new MyBundle).Lit(_.a -> 42.U, _.b -> true.B, _.c -> MyEnum.sB) - assertTesterPasses { - new BasicTester { - // TODO: add direct bundle compare operations, when that feature is added - chisel3.assert(outsideBundleLit.a === 42.U) - chisel3.assert(outsideBundleLit.b === true.B) - chisel3.assert(outsideBundleLit.c === MyEnum.sB) - chisel3.assert(outsideBundleLit.isLit()) - chisel3.assert(outsideBundleLit.litValue().U === outsideBundleLit.asUInt()) - val bundleLit = (new MyBundle).Lit(_.a -> 42.U, _.b -> true.B, _.c -> MyEnum.sB) - chisel3.assert(bundleLit.a === 42.U) - chisel3.assert(bundleLit.b === true.B) - chisel3.assert(bundleLit.c === MyEnum.sB) - - chisel3.assert(bundleLit.a === outsideBundleLit.a) - chisel3.assert(bundleLit.b === outsideBundleLit.b) - chisel3.assert(bundleLit.c === outsideBundleLit.c) - - val bundleWire = Wire(new MyBundle) - bundleWire := outsideBundleLit - - chisel3.assert(bundleWire.a === 42.U) - chisel3.assert(bundleWire.b === true.B) - chisel3.assert(bundleWire.c === MyEnum.sB) - - stop() - } - } - } - - "bundle literals of vec literals" should "work" in { - assertTesterPasses(new BasicTester { - val range = range"[0,4].2" - val bundleWithVecs = new Bundle { - val a = Vec(2, UInt(4.W)) - val b = Vec(2, Interval(range)) - }.Lit( - _.a -> Vec(2, UInt(4.W)).Lit(0 -> 0xa.U, 1 -> 0xb.U), - _.b -> Vec(2, Interval(range)).Lit(0 -> (1.5).I(range), 1 -> (0.25).I(range)) - ) - chisel3.assert(bundleWithVecs.a(0) === 0xa.U) - chisel3.assert(bundleWithVecs.a(1) === 0xb.U) - chisel3.assert(bundleWithVecs.b(0) === (1.5).I(range)) - chisel3.assert(bundleWithVecs.b(1) === (0.25).I(range)) - stop() - }) - } - - "partial bundle literals" should "work in RTL" in { - assertTesterPasses { - new BasicTester { - val bundleLit = (new MyBundle).Lit(_.a -> 42.U) - chisel3.assert(bundleLit.a === 42.U) - - val bundleWire = Wire(new MyBundle) - bundleWire := bundleLit - - chisel3.assert(bundleWire.a === 42.U) - - stop() - } - } - } - - class MyOuterBundle extends Bundle { - val a = new MyBundle - val b = new Bundle { - val c = Bool() - val d = UInt(8.W) - val e = MyEnum() - } - val f = MyEnum() - } - - "contained bundles" should "work" in { - assertTesterPasses { - new BasicTester { - // Specify the inner Bundle value as a Bundle literal - val explicitBundleLit = (new MyOuterBundle).Lit( - _.a -> (new MyBundle).Lit(_.a -> 42.U, _.b -> true.B, _.c -> MyEnum.sB) - ) - chisel3.assert(explicitBundleLit.a.a === 42.U) - chisel3.assert(explicitBundleLit.a.b === true.B) - chisel3.assert(explicitBundleLit.a.c === MyEnum.sB) - chisel3.assert(explicitBundleLit.a.isLit()) - chisel3.assert(explicitBundleLit.a.litValue().U === explicitBundleLit.a.asUInt()) - - // Specify the inner Bundle fields directly - val expandedBundleLit = (new MyOuterBundle).Lit( - _.a.a -> 42.U, - _.a.b -> true.B, - _.b.c -> false.B, - _.b.d -> 255.U, - _.b.e -> MyEnum.sB, - _.f -> MyEnum.sB - ) - chisel3.assert(expandedBundleLit.a.a === 42.U) - chisel3.assert(expandedBundleLit.a.b === true.B) - chisel3.assert(expandedBundleLit.f === MyEnum.sB) - chisel3.assert(expandedBundleLit.b.c === false.B) - chisel3.assert(expandedBundleLit.b.d === 255.U) - chisel3.assert(expandedBundleLit.b.e === MyEnum.sB) - chisel3.assert(!expandedBundleLit.a.isLit()) // element e is missing - chisel3.assert(expandedBundleLit.b.isLit()) - chisel3.assert(!expandedBundleLit.isLit()) // element a.e is missing - chisel3.assert(expandedBundleLit.b.litValue().U === expandedBundleLit.b.asUInt()) - - // Anonymously contruct the inner Bundle literal - // A bit of weird syntax that depends on implementation details of the Bundle literal constructor - val childBundleLit = - (new MyOuterBundle).Lit(b => b.b -> b.b.Lit(_.c -> false.B, _.d -> 255.U, _.e -> MyEnum.sB)) - chisel3.assert(childBundleLit.b.c === false.B) - chisel3.assert(childBundleLit.b.d === 255.U) - chisel3.assert(childBundleLit.b.e === MyEnum.sB) - chisel3.assert(childBundleLit.b.isLit()) - chisel3.assert(!childBundleLit.isLit()) // elements a and f are missing - chisel3.assert(childBundleLit.b.litValue().U === childBundleLit.b.asUInt()) - - stop() - } - } - } - - "Bundle literals" should "assign" in { - assertTesterPasses { - new BasicTester { - val bundleWire = Wire(Output(new MyBundle)) - val bundleLit = (new MyBundle).Lit(_.a -> 42.U, _.b -> true.B, _.c -> MyEnum.sB) - bundleWire := bundleLit - - chisel3.assert(bundleWire.a === 42.U) - chisel3.assert(bundleWire.b === true.B) - chisel3.assert(bundleWire.c === MyEnum.sB) - stop() - } - } - } - - "partially initialized Bundle literals" should "assign" in { - assertTesterPasses { - new BasicTester { - val bundleWire = Wire(Output(new MyBundle)) - val bundleLit = (new MyBundle).Lit(_.a -> 42.U) - bundleWire := bundleLit - - chisel3.assert(bundleWire.a === 42.U) - stop() - } - } - } - - "Bundle literals" should "work as register reset values" in { - assertTesterPasses { - new BasicTester { - val r = RegInit((new MyBundle).Lit(_.a -> 42.U, _.b -> true.B, _.c -> MyEnum.sB)) - r := (r.asUInt + 1.U).asTypeOf(new MyBundle) // prevent constprop - - // check reset values on first cycle out of reset - chisel3.assert(r.a === 42.U) - chisel3.assert(r.b === true.B) - chisel3.assert(r.c === MyEnum.sB) - stop() - } - } - } - - "partially initialized Bundle literals" should "work as register reset values" in { - assertTesterPasses { - new BasicTester { - val r = RegInit((new MyBundle).Lit(_.a -> 42.U)) - r.a := r.a + 1.U // prevent const prop - chisel3.assert(r.a === 42.U) // coming out of reset - stop() - } - } - } - - "Fields extracted from BundleLiterals" should "work as register reset values" in { - assertTesterPasses { - new BasicTester { - val r = RegInit((new MyBundle).Lit(_.a -> 42.U).a) - r := r + 1.U // prevent const prop - chisel3.assert(r === 42.U) // coming out of reset - stop() - } - } - } - - "DontCare fields extracted from BundleLiterals" should "work as register reset values" in { - assertTesterPasses { - new BasicTester { - val r = RegInit((new MyBundle).Lit(_.a -> 42.U).b) - r := reset.asBool - printf(p"r = $r\n") // Can't assert because reset value is DontCare - stop() - } - } - } - - "DontCare fields extracted from BundleLiterals" should "work in other Expressions" in { - assertTesterPasses { - new BasicTester { - val x = (new MyBundle).Lit(_.a -> 42.U).b || true.B - chisel3.assert(x === true.B) - stop() - } - } - } - - "bundle literals with bad field specifiers" should "fail" in { - val exc = intercept[BundleLiteralException] { - extractCause[BundleLiteralException] { - ChiselStage.elaborate { - new RawModule { - val bundle = new MyBundle - bundle.Lit(x => bundle.a -> 0.U) // DONT DO THIS, this gets past a syntax error to exercise the failure - } - } - } - } - exc.getMessage should include("not a field") - } - - "bundle literals with duplicate fields" should "fail" in { - val exc = intercept[BundleLiteralException] { - extractCause[BundleLiteralException] { - ChiselStage.elaborate { - new RawModule { - (new MyBundle).Lit(_.a -> 0.U, _.a -> 0.U) - } - } - } - } - exc.getMessage should include("duplicate") - exc.getMessage should include(".a") - } - - "bundle literals with non-literal values" should "fail" in { - val exc = intercept[BundleLiteralException] { - extractCause[BundleLiteralException] { - ChiselStage.elaborate { - new RawModule { - (new MyBundle).Lit(_.a -> UInt()) - } - } - } - } - exc.getMessage should include("non-literal value") - exc.getMessage should include(".a") - } - - "bundle literals with non-type-equivalent element fields" should "fail" in { - val exc = intercept[BundleLiteralException] { - extractCause[BundleLiteralException] { - ChiselStage.elaborate { - new RawModule { - (new MyBundle).Lit(_.a -> true.B) - } - } - } - } - exc.getMessage should include("non-type-equivalent value") - exc.getMessage should include(".a") - } - - "bundle literals with non-type-equivalent sub-bundles" should "fail" in { - val exc = intercept[BundleLiteralException] { - extractCause[BundleLiteralException] { - ChiselStage.elaborate { - new RawModule { - (new MyOuterBundle).Lit(_.b -> (new MyBundle).Lit(_.a -> 0.U)) - } - } - } - } - exc.getMessage should include("non-type-equivalent value") - exc.getMessage should include(".b") - } - - "bundle literals with non-type-equivalent enum element fields" should "fail" in { - val exc = intercept[BundleLiteralException] { - extractCause[BundleLiteralException] { - ChiselStage.elaborate { - new RawModule { - (new MyBundle).Lit(_.c -> MyEnumB.sB) - } - } - } - } - exc.getMessage should include("non-type-equivalent enum value") - exc.getMessage should include(".c") - } - - "partial bundle literals" should "fail to pack" in { - ChiselStage.elaborate { - new RawModule { - val bundleLit = (new MyBundle).Lit(_.a -> 42.U) - bundleLit.litOption should equal(None) - } - } - } -} diff --git a/src/test/scala/chiselTests/BundleSpec.scala b/src/test/scala/chiselTests/BundleSpec.scala deleted file mode 100644 index 2d34b263..00000000 --- a/src/test/scala/chiselTests/BundleSpec.scala +++ /dev/null @@ -1,187 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.util.Decoupled -import chisel3.stage.ChiselStage -import chisel3.testers.BasicTester - -trait BundleSpecUtils { - class BundleFooBar extends Bundle { - val foo = UInt(16.W) - val bar = UInt(16.W) - } - class BundleBarFoo extends Bundle { - val bar = UInt(16.W) - val foo = UInt(16.W) - } - class BundleFoo extends Bundle { - val foo = UInt(16.W) - } - class BundleBar extends Bundle { - val bar = UInt(16.W) - } - - class BadSeqBundle extends Bundle { - val bar = Seq(UInt(16.W), UInt(8.W), UInt(4.W)) - } - - class BadSeqBundleWithIgnoreSeqInBundle extends Bundle with IgnoreSeqInBundle { - val bar = Seq(UInt(16.W), UInt(8.W), UInt(4.W)) - } - - class MyModule(output: Bundle, input: Bundle) extends Module { - val io = IO(new Bundle { - val in = Input(input) - val out = Output(output) - }) - io.out <> io.in - } - - class BundleSerializationTest extends BasicTester { - // Note that foo is higher order because its defined earlier in the Bundle - val bundle = Wire(new BundleFooBar) - bundle.foo := 0x1234.U - bundle.bar := 0x5678.U - // To UInt - val uint = bundle.asUInt - assert(uint.getWidth == 32) // elaboration time - assert(uint === "h12345678".asUInt(32.W)) - // Back to Bundle - val bundle2 = uint.asTypeOf(new BundleFooBar) - assert(0x1234.U === bundle2.foo) - assert(0x5678.U === bundle2.bar) - stop() - } -} - -class BundleSpec extends ChiselFlatSpec with BundleSpecUtils with Utils { - "Bundles with the same fields but in different orders" should "bulk connect" in { - ChiselStage.elaborate { new MyModule(new BundleFooBar, new BundleBarFoo) } - } - - "Bundles" should "follow UInt serialization/deserialization API" in { - assertTesterPasses { new BundleSerializationTest } - } - - "Bulk connect on Bundles" should "check that the fields match" in { - (the[ChiselException] thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { new MyModule(new BundleFooBar, new BundleFoo) } - }).getMessage should include("Right Record missing field") - - (the[ChiselException] thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { new MyModule(new BundleFoo, new BundleFooBar) } - }).getMessage should include("Left Record missing field") - } - - "Bundles" should "not be able to use Seq for constructing hardware" in { - (the[ChiselException] thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { - new Module { - val io = IO(new Bundle { - val b = new BadSeqBundle - }) - } - } - }).getMessage should include("Public Seq members cannot be used to define Bundle elements") - } - - "Bundles" should "be allowed to have Seq if need be" in { - assertTesterPasses { - new BasicTester { - val m = Module(new Module { - val io = IO(new Bundle { - val b = new BadSeqBundleWithIgnoreSeqInBundle - }) - }) - stop() - } - } - } - - "Bundles" should "be allowed to have non-Chisel Seqs" in { - assertTesterPasses { - new BasicTester { - val m = Module(new Module { - val io = IO(new Bundle { - val f = Output(UInt(8.W)) - val unrelated = (0 to 10).toSeq - val unrelated2 = Seq("Hello", "World", "Chisel") - }) - io.f := 0.U - }) - stop() - } - } - } - - "Bundles" should "with aliased fields, should show a helpful error message" in { - class AliasedBundle extends Bundle { - val a = UInt(8.W) - val b = a - val c = SInt(8.W) - val d = c - } - - (the[ChiselException] thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { - new Module { - val io = IO(Output(new AliasedBundle)) - io.a := 0.U - io.b := 1.U - } - } - }).getMessage should include("contains aliased fields named (a,b),(c,d)") - } - - "Bundles" should "not have bound hardware" in { - (the[ChiselException] thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { - new Module { - class MyBundle(val foo: UInt) extends Bundle - val in = IO(Input(new MyBundle(123.U))) // This should error: value passed in instead of type - val out = IO(Output(new MyBundle(UInt(8.W)))) - - out := in - } - } - }).getMessage should include("MyBundle contains hardware fields: foo: UInt<7>(123)") - } - "Bundles" should "not recursively contain aggregates with bound hardware" in { - (the[ChiselException] thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { - new Module { - class MyBundle(val foo: UInt) extends Bundle - val out = IO(Output(Vec(2, UInt(8.W)))) - val in = IO(Input(new MyBundle(out(0)))) // This should error: Bound aggregate passed - out := in - } - } - }).getMessage should include("Bundle: MyBundle contains hardware fields: foo: BundleSpec_Anon.out") - } - "Unbound bundles sharing a field" should "not error" in { - ChiselStage.elaborate { - new RawModule { - val foo = new Bundle { - val x = UInt(8.W) - } - val bar = new Bundle { - val y = foo.x - } - } - } - } - - // This tests the interaction of override def cloneType and the plugin. - // We are commenting it for now because although this code fails to compile - // as expected when just copied here, the test version is not seeing the failure. - // """ - // class BundleBaz(w: Int) extends Bundle { - // val baz = UInt(w.W) - // // This is a compiler error when using the plugin, which we test below. - // override def cloneType = (new BundleBaz(w)).asInstanceOf[this.type] - // } - // """ shouldNot compile - -} diff --git a/src/test/scala/chiselTests/BundleWire.scala b/src/test/scala/chiselTests/BundleWire.scala deleted file mode 100644 index 3b58d52a..00000000 --- a/src/test/scala/chiselTests/BundleWire.scala +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests -import chisel3._ -import chisel3.testers.BasicTester - -class Coord extends Bundle { - val x = UInt(32.W) - val y = UInt(32.W) -} - -class BundleWire(n: Int) extends Module { - val io = IO(new Bundle { - val in = Input(new Coord) - val outs = Output(Vec(n, new Coord)) - }) - val coords = Wire(Vec(n, new Coord)) - for (i <- 0 until n) { - coords(i) := io.in - io.outs(i) := coords(i) - } -} - -class BundleToUnitTester extends BasicTester { - val bundle1 = Wire(new Bundle { - val a = UInt(4.W) - val b = UInt(4.W) - }) - val bundle2 = Wire(new Bundle { - val a = UInt(2.W) - val b = UInt(6.W) - }) - - // 0b00011011 split as 0001 1011 and as 00 011011 - bundle1.a := 1.U - bundle1.b := 11.U - bundle2.a := 0.U - bundle2.b := 27.U - - assert(bundle1.asUInt() === bundle2.asUInt()) - - stop() -} - -class BundleWireTester(n: Int, x: Int, y: Int) extends BasicTester { - val dut = Module(new BundleWire(n)) - dut.io.in.x := x.asUInt - dut.io.in.y := y.asUInt - for (elt <- dut.io.outs) { - assert(elt.x === x.asUInt) - assert(elt.y === y.asUInt) - } - stop() -} - -class BundleWireSpec extends ChiselPropSpec { - - property("All vec elems should match the inputs") { - forAll(vecSizes, safeUInts, safeUInts) { (n: Int, x: Int, y: Int) => - assertTesterPasses { new BundleWireTester(n, x, y) } - } - } -} - -class BundleToUIntSpec extends ChiselPropSpec { - property("Bundles with same data but different, underlying elements should compare as UInt") { - assertTesterPasses(new BundleToUnitTester) - } -} diff --git a/src/test/scala/chiselTests/ChiselEnum.scala b/src/test/scala/chiselTests/ChiselEnum.scala deleted file mode 100644 index dbad273b..00000000 --- a/src/test/scala/chiselTests/ChiselEnum.scala +++ /dev/null @@ -1,824 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.experimental.AffectsChiselPrefix -import chisel3.internal.firrtl.UnknownWidth -import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} -import chisel3.util._ -import chisel3.testers.BasicTester -import org.scalatest.Assertion -import org.scalatest.freespec.AnyFreeSpec -import org.scalatest.matchers.should.Matchers - -object EnumExample extends ChiselEnum { - val e0, e1, e2 = Value - - val e100 = Value(100.U) - val e101 = Value(101.U) - - val litValues = List(0.U, 1.U, 2.U, 100.U, 101.U) -} - -object OtherEnum extends ChiselEnum { - val otherEnum = Value -} - -object NonLiteralEnumType extends ChiselEnum { - val nonLit = Value(UInt()) -} - -object NonIncreasingEnum extends ChiselEnum { - val x = Value(2.U) - val y = Value(2.U) -} - -class SimpleConnector(inType: Data, outType: Data) extends Module { - val io = IO(new Bundle { - val in = Input(inType) - val out = Output(outType) - }) - - io.out := io.in -} - -class CastToUInt extends Module { - val io = IO(new Bundle { - val in = Input(EnumExample()) - val out = Output(UInt()) - }) - - io.out := io.in.asUInt() -} - -class CastFromLit(in: UInt) extends Module { - val io = IO(new Bundle { - val out = Output(EnumExample()) - val valid = Output(Bool()) - }) - - io.out := EnumExample(in) - io.valid := io.out.isValid -} - -class CastFromNonLit extends Module { - val io = IO(new Bundle { - val in = Input(UInt(EnumExample.getWidth.W)) - val out = Output(EnumExample()) - val valid = Output(Bool()) - }) - - io.out := EnumExample(io.in) - io.valid := io.out.isValid -} - -class SafeCastFromNonLit extends Module { - val io = IO(new Bundle { - val in = Input(UInt(EnumExample.getWidth.W)) - val out = Output(EnumExample()) - val valid = Output(Bool()) - }) - - val (enum, valid) = EnumExample.safe(io.in) - io.out := enum - io.valid := valid -} - -class CastFromNonLitWidth(w: Option[Int] = None) extends Module { - val width = if (w.isDefined) w.get.W else UnknownWidth() - - val io = IO(new Bundle { - val in = Input(UInt(width)) - val out = Output(EnumExample()) - }) - - io.out := EnumExample(io.in) -} - -class EnumOps(val xType: ChiselEnum, val yType: ChiselEnum) extends Module { - val io = IO(new Bundle { - val x = Input(xType()) - val y = Input(yType()) - - val lt = Output(Bool()) - val le = Output(Bool()) - val gt = Output(Bool()) - val ge = Output(Bool()) - val eq = Output(Bool()) - val ne = Output(Bool()) - }) - - io.lt := io.x < io.y - io.le := io.x <= io.y - io.gt := io.x > io.y - io.ge := io.x >= io.y - io.eq := io.x === io.y - io.ne := io.x =/= io.y -} - -object ChiselEnumFSM { - object State extends ChiselEnum { - val sNone, sOne1, sTwo1s = Value - - val correct_annotation_map = Map[String, BigInt]("sNone" -> 0, "sOne1" -> 1, "sTwo1s" -> 2) - } -} - -class ChiselEnumFSM extends Module { - import ChiselEnumFSM.State - import ChiselEnumFSM.State._ - - // This FSM detects two 1's one after the other - val io = IO(new Bundle { - val in = Input(Bool()) - val out = Output(Bool()) - val state = Output(State()) - }) - - val state = RegInit(sNone) - - io.out := (state === sTwo1s) - io.state := state - - switch(state) { - is(sNone) { - when(io.in) { - state := sOne1 - } - } - is(sOne1) { - when(io.in) { - state := sTwo1s - }.otherwise { - state := sNone - } - } - is(sTwo1s) { - when(!io.in) { - state := sNone - } - } - } -} - -object Opcode extends ChiselEnum { - val load = Value(0x03.U) - val imm = Value(0x13.U) - val auipc = Value(0x17.U) - val store = Value(0x23.U) - val reg = Value(0x33.U) - val lui = Value(0x37.U) - val br = Value(0x63.U) - val jalr = Value(0x67.U) - val jal = Value(0x6f.U) -} - -class LoadStoreExample extends Module { - val io = IO(new Bundle { - val opcode = Input(Opcode()) - val load_or_store = Output(Bool()) - }) - io.load_or_store := io.opcode.isOneOf(Opcode.load, Opcode.store) - printf(p"${io.opcode}") -} - -class CastToUIntTester extends BasicTester { - for ((enum, lit) <- EnumExample.all.zip(EnumExample.litValues)) { - val mod = Module(new CastToUInt) - mod.io.in := enum - assert(mod.io.out === lit) - } - stop() -} - -class CastFromLitTester extends BasicTester { - for ((enum, lit) <- EnumExample.all.zip(EnumExample.litValues)) { - val mod = Module(new CastFromLit(lit)) - assert(mod.io.out === enum) - assert(mod.io.valid === true.B) - } - stop() -} - -class CastFromNonLitTester extends BasicTester { - for ((enum, lit) <- EnumExample.all.zip(EnumExample.litValues)) { - val mod = Module(new CastFromNonLit) - mod.io.in := lit - assert(mod.io.out === enum) - assert(mod.io.valid === true.B) - } - - val invalid_values = - (1 until (1 << EnumExample.getWidth)).filter(!EnumExample.litValues.map(_.litValue).contains(_)).map(_.U) - - for (invalid_val <- invalid_values) { - val mod = Module(new CastFromNonLit) - mod.io.in := invalid_val - - assert(mod.io.valid === false.B) - } - - stop() -} - -class SafeCastFromNonLitTester extends BasicTester { - for ((enum, lit) <- EnumExample.all.zip(EnumExample.litValues)) { - val mod = Module(new SafeCastFromNonLit) - mod.io.in := lit - assert(mod.io.out === enum) - assert(mod.io.valid === true.B) - } - - val invalid_values = - (1 until (1 << EnumExample.getWidth)).filter(!EnumExample.litValues.map(_.litValue).contains(_)).map(_.U) - - for (invalid_val <- invalid_values) { - val mod = Module(new SafeCastFromNonLit) - mod.io.in := invalid_val - - assert(mod.io.valid === false.B) - } - - stop() -} - -class CastToInvalidEnumTester extends BasicTester { - val invalid_value: UInt = EnumExample.litValues.last + 1.U - Module(new CastFromLit(invalid_value)) -} - -class EnumOpsTester extends BasicTester { - for { - x <- EnumExample.all - y <- EnumExample.all - } { - val mod = Module(new EnumOps(EnumExample, EnumExample)) - mod.io.x := x - mod.io.y := y - - assert(mod.io.lt === (x.asUInt() < y.asUInt())) - assert(mod.io.le === (x.asUInt() <= y.asUInt())) - assert(mod.io.gt === (x.asUInt() > y.asUInt())) - assert(mod.io.ge === (x.asUInt() >= y.asUInt())) - assert(mod.io.eq === (x.asUInt() === y.asUInt())) - assert(mod.io.ne === (x.asUInt() =/= y.asUInt())) - } - stop() -} - -class InvalidEnumOpsTester extends BasicTester { - val mod = Module(new EnumOps(EnumExample, OtherEnum)) - mod.io.x := EnumExample.e0 - mod.io.y := OtherEnum.otherEnum -} - -class IsLitTester extends BasicTester { - for (e <- EnumExample.all) { - val wire = WireDefault(e) - - assert(e.isLit) - assert(!wire.isLit) - } - stop() -} - -class NextTester extends BasicTester { - for ((e, n) <- EnumExample.all.zip(EnumExample.litValues.tail :+ EnumExample.litValues.head)) { - assert(e.next.litValue == n.litValue) - val w = WireDefault(e) - assert(w.next === EnumExample(n)) - } - stop() -} - -class WidthTester extends BasicTester { - assert(EnumExample.getWidth == EnumExample.litValues.last.getWidth) - assert(EnumExample.all.forall(_.getWidth == EnumExample.litValues.last.getWidth)) - assert(EnumExample.all.forall { e => - val w = WireDefault(e) - w.getWidth == EnumExample.litValues.last.getWidth - }) - stop() -} - -class ChiselEnumFSMTester extends BasicTester { - import ChiselEnumFSM.State._ - - val dut = Module(new ChiselEnumFSM) - - // Inputs and expected results - val inputs: Vec[Bool] = VecInit(false.B, true.B, false.B, true.B, true.B, true.B, false.B, true.B, true.B, false.B) - val expected: Vec[Bool] = - VecInit(false.B, false.B, false.B, false.B, false.B, true.B, true.B, false.B, false.B, true.B) - val expected_state = VecInit(sNone, sNone, sOne1, sNone, sOne1, sTwo1s, sTwo1s, sNone, sOne1, sTwo1s) - - val cntr = Counter(inputs.length) - val cycle = cntr.value - - dut.io.in := inputs(cycle) - assert(dut.io.out === expected(cycle)) - assert(dut.io.state === expected_state(cycle)) - - when(cntr.inc()) { - stop() - } -} - -class IsOneOfTester extends BasicTester { - import EnumExample._ - - // is one of itself - assert(e0.isOneOf(e0)) - - // is one of Seq of itself - assert(e0.isOneOf(Seq(e0))) - assert(e0.isOneOf(Seq(e0, e0, e0, e0))) - assert(e0.isOneOf(e0, e0, e0, e0)) - - // is one of Seq of multiple elements - val subset = Seq(e0, e1, e2) - assert(e0.isOneOf(subset)) - assert(e1.isOneOf(subset)) - assert(e2.isOneOf(subset)) - - // is not element not in subset - assert(!e100.isOneOf(subset)) - assert(!e101.isOneOf(subset)) - - // test multiple elements with variable number of arguments - assert(e0.isOneOf(e0, e1, e2)) - assert(e1.isOneOf(e0, e1, e2)) - assert(e2.isOneOf(e0, e1, e2)) - assert(!e100.isOneOf(e0, e1, e2)) - assert(!e101.isOneOf(e0, e1, e2)) - - // is not another value - assert(!e0.isOneOf(e1)) - assert(!e2.isOneOf(e101)) - - stop() -} - -class ChiselEnumSpec extends ChiselFlatSpec with Utils { - import chisel3.internal.ChiselException - - behavior.of("ChiselEnum") - - it should "fail to instantiate non-literal enums with the Value function" in { - an[ExceptionInInitializerError] should be thrownBy extractCause[ExceptionInInitializerError] { - ChiselStage.elaborate(new SimpleConnector(NonLiteralEnumType(), NonLiteralEnumType())) - } - } - - it should "fail to instantiate non-increasing enums with the Value function" in { - an[ExceptionInInitializerError] should be thrownBy extractCause[ExceptionInInitializerError] { - ChiselStage.elaborate(new SimpleConnector(NonIncreasingEnum(), NonIncreasingEnum())) - } - } - - it should "connect enums of the same type" in { - ChiselStage.elaborate(new SimpleConnector(EnumExample(), EnumExample())) - ChiselStage.elaborate(new SimpleConnector(EnumExample(), EnumExample.Type())) - } - - it should "fail to connect a strong enum to a UInt" in { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate(new SimpleConnector(EnumExample(), UInt())) - } - } - - it should "fail to connect enums of different types" in { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate(new SimpleConnector(EnumExample(), OtherEnum())) - } - - a[ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate(new SimpleConnector(EnumExample.Type(), OtherEnum.Type())) - } - } - - it should "cast enums to UInts correctly" in { - assertTesterPasses(new CastToUIntTester) - } - - it should "cast literal UInts to enums correctly" in { - assertTesterPasses(new CastFromLitTester) - } - - it should "cast non-literal UInts to enums correctly and detect illegal casts" in { - assertTesterPasses(new CastFromNonLitTester) - } - - it should "safely cast non-literal UInts to enums correctly and detect illegal casts" in { - assertTesterPasses(new SafeCastFromNonLitTester) - } - - it should "prevent illegal literal casts to enums" in { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate(new CastToInvalidEnumTester) - } - } - - it should "only allow non-literal casts to enums if the width is smaller than or equal to the enum width" in { - for (w <- 0 to EnumExample.getWidth) - ChiselStage.elaborate(new CastFromNonLitWidth(Some(w))) - - a[ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate(new CastFromNonLitWidth) - } - - for (w <- (EnumExample.getWidth + 1) to (EnumExample.getWidth + 100)) { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate(new CastFromNonLitWidth(Some(w))) - } - } - } - - it should "execute enum comparison operations correctly" in { - assertTesterPasses(new EnumOpsTester) - } - - it should "fail to compare enums of different types" in { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate(new InvalidEnumOpsTester) - } - } - - it should "correctly check whether or not enums are literal" in { - assertTesterPasses(new IsLitTester) - } - - it should "return the correct next values for enums" in { - assertTesterPasses(new NextTester) - } - - it should "return the correct widths for enums" in { - assertTesterPasses(new WidthTester) - } - - it should "maintain Scala-level type-safety" in { - def foo(e: EnumExample.Type): Unit = {} - - "foo(EnumExample.e1); foo(EnumExample.e1.next)" should compile - "foo(OtherEnum.otherEnum)" shouldNot compile - } - - it should "prevent enums from being declared without names" in { - "object UnnamedEnum extends ChiselEnum { Value }" shouldNot compile - } - - "ChiselEnum FSM" should "work" in { - assertTesterPasses(new ChiselEnumFSMTester) - } - - "Casting a UInt to an Enum" should "warn if the UInt can express illegal states" in { - object MyEnum extends ChiselEnum { - val e0, e1, e2 = Value - } - - class MyModule extends Module { - val in = IO(Input(UInt(2.W))) - val out = IO(Output(MyEnum())) - out := MyEnum(in) - } - val (log, _) = grabLog(ChiselStage.elaborate(new MyModule)) - log should include("warn") - log should include("Casting non-literal UInt") - } - - it should "NOT warn if the Enum is total" in { - object TotalEnum extends ChiselEnum { - val e0, e1, e2, e3 = Value - } - - class MyModule extends Module { - val in = IO(Input(UInt(2.W))) - val out = IO(Output(TotalEnum())) - out := TotalEnum(in) - } - val (log, _) = grabLog(ChiselStage.elaborate(new MyModule)) - (log should not).include("warn") - } - - it should "suppress warning using suppressEnumCastWarning" in { - object TestEnum extends ChiselEnum { - val e0, e1, e2 = Value - } - - class MyModule extends Module { - val in = IO(Input(UInt(2.W))) - val out = IO(Output(TestEnum())) - suppressEnumCastWarning { - val res = TestEnum(in) - out := res - } - } - val (log, _) = grabLog(ChiselStage.elaborate(new MyModule)) - (log should not).include("warn") - } - - it should "suppress exactly one warning using suppressEnumCastWarning" in { - object TestEnum1 extends ChiselEnum { - val e0, e1, e2 = Value - } - object TestEnum2 extends ChiselEnum { - val e0, e1, e2 = Value - } - - class MyModule extends Module { - val in = IO(Input(UInt(2.W))) - val out1 = IO(Output(TestEnum1())) - val out2 = IO(Output(TestEnum2())) - suppressEnumCastWarning { - out1 := TestEnum1(in) - } - out2 := TestEnum2(in) - } - val (log, _) = grabLog(ChiselStage.elaborate(new MyModule)) - log should include("warn") - log should include("TestEnum2") // not suppressed - (log should not).include("TestEnum1") // suppressed - } - - "Casting a UInt to an Enum with .safe" should "NOT warn" in { - object MyEnum extends ChiselEnum { - val e0, e1, e2 = Value - } - - class MyModule extends Module { - val in = IO(Input(UInt(2.W))) - val out = IO(Output(MyEnum())) - out := MyEnum.safe(in)._1 - } - val (log, _) = grabLog(ChiselStage.elaborate(new MyModule)) - (log should not).include("warn") - } - - it should "NOT generate any validity logic if the Enum is total" in { - object TotalEnum extends ChiselEnum { - val e0, e1, e2, e3 = Value - } - - class MyModule extends Module { - val in = IO(Input(UInt(2.W))) - val out = IO(Output(TotalEnum())) - val (res, valid) = TotalEnum.safe(in) - assert(valid.litToBoolean, "It should be true.B") - out := res - } - val (log, _) = grabLog(ChiselStage.elaborate(new MyModule)) - (log should not).include("warn") - } - - it should "correctly check if the enumeration is one of the values in a given sequence" in { - assertTesterPasses(new IsOneOfTester) - } - - it should "work with Printables" in { - ChiselStage.emitChirrtl(new LoadStoreExample) should include( - """printf(clock, UInt<1>("h1"), "%c%c%c%c%c", _chiselTestsOpcodePrintable[0], _chiselTestsOpcodePrintable[1], _chiselTestsOpcodePrintable[2], _chiselTestsOpcodePrintable[3], _chiselTestsOpcodePrintable[4])""" - ) - } -} - -class ChiselEnumAnnotator extends Module { - import EnumExample._ - - object LocalEnum extends ChiselEnum { - val le0, le1 = Value - val le2 = Value - val le100 = Value(100.U) - } - - val io = IO(new Bundle { - val in = Input(EnumExample()) - val out = Output(EnumExample()) - val other = Output(OtherEnum()) - val local = Output(LocalEnum()) - }) - - class Bund extends Bundle { - val field = EnumExample() - val other = OtherEnum() - val local = LocalEnum() - val vec = Vec(5, EnumExample()) - val inner_bundle1 = new Bundle { - val x = UInt(4.W) - val y = Vec(3, UInt(4.W)) - val e = EnumExample() - val v = Vec(3, EnumExample()) - } - val inner_bundle2 = new Bundle {} - val inner_bundle3 = new Bundle { - val x = Bool() - } - val inner_bundle4 = new Bundle { - val inner_inner_bundle = new Bundle {} - } - } - - val simple = Wire(EnumExample()) - val vec = VecInit(e0, e1, e2) - val vec_of_vecs = VecInit(VecInit(e0, e1), VecInit(e100, e101)) - - val bund = Wire(new Bund()) - val vec_of_bundles = Wire(Vec(5, new Bund())) - - io.out := e101 - io.other := OtherEnum.otherEnum - io.local := LocalEnum.le0 - simple := e100 - bund := DontCare - vec_of_bundles := DontCare - - // Make sure that dynamically indexing into a Vec of enums will not cause an elaboration error. - // The components created here will not be annotated. - val cycle = RegInit(0.U) - cycle := cycle + 1.U - - val indexed1 = vec_of_vecs(cycle)(cycle) - val indexed2 = vec_of_bundles(cycle) -} - -class ChiselEnumAnnotatorWithChiselName extends Module { - import EnumExample._ - - object LocalEnum extends ChiselEnum with AffectsChiselPrefix { - val le0, le1 = Value - val le2 = Value - val le100 = Value(100.U) - } - - val io = IO(new Bundle { - val in = Input(EnumExample()) - val out = Output(EnumExample()) - val other = Output(OtherEnum()) - val local = Output(LocalEnum()) - }) - - class Bund extends Bundle { - val field = EnumExample() - val other = OtherEnum() - val local = LocalEnum() - val vec = Vec(5, EnumExample()) - val inner_bundle1 = new Bundle { - val x = UInt(4.W) - val y = Vec(3, UInt(4.W)) - val e = EnumExample() - val v = Vec(3, EnumExample()) - } - val inner_bundle2 = new Bundle {} - val inner_bundle3 = new Bundle { - val x = Bool() - } - val inner_bundle4 = new Bundle { - val inner_inner_bundle = new Bundle {} - } - } - - val simple = Wire(EnumExample()) - val vec = VecInit(e0, e1, e2) - val vec_of_vecs = VecInit(VecInit(e0, e1), VecInit(e100, e101)) - - val bund = Wire(new Bund()) - val vec_of_bundles = Wire(Vec(5, new Bund())) - - io.out := e101 - io.other := OtherEnum.otherEnum - io.local := LocalEnum.le0 - simple := e100 - bund := DontCare - vec_of_bundles := DontCare - - // Make sure that dynamically indexing into a Vec of enums will not cause an elaboration error. - // The components created here will not be annotated. - val cycle = RegInit(0.U) - cycle := cycle + 1.U - - val indexed1 = vec_of_vecs(cycle)(cycle) - val indexed2 = vec_of_bundles(cycle) -} - -class ChiselEnumAnnotationSpec extends AnyFreeSpec with Matchers { - import chisel3.experimental.EnumAnnotations._ - import firrtl.annotations.{Annotation, ComponentName} - - val enumExampleName = "EnumExample" - val otherEnumName = "OtherEnum" - val localEnumName = "LocalEnum" - - case class CorrectDefAnno(typeName: String, definition: Map[String, BigInt]) - case class CorrectCompAnno(targetName: String, typeName: String) - case class CorrectVecAnno(targetName: String, typeName: String, fields: Set[Seq[String]]) - - val correctDefAnnos = Seq( - CorrectDefAnno(otherEnumName, Map("otherEnum" -> 0)), - CorrectDefAnno(enumExampleName, Map("e0" -> 0, "e1" -> 1, "e2" -> 2, "e100" -> 100, "e101" -> 101)), - CorrectDefAnno(localEnumName, Map("le0" -> 0, "le1" -> 1, "le2" -> 2, "le100" -> 100)) - ) - - val correctCompAnnos = Seq( - CorrectCompAnno("io.other", otherEnumName), - CorrectCompAnno("io.local", localEnumName), - CorrectCompAnno("io.out", enumExampleName), - CorrectCompAnno("io.in", enumExampleName), - CorrectCompAnno("simple", enumExampleName), - CorrectCompAnno("bund.field", enumExampleName), - CorrectCompAnno("bund.other", otherEnumName), - CorrectCompAnno("bund.local", localEnumName), - CorrectCompAnno("bund.inner_bundle1.e", enumExampleName) - ) - - val correctVecAnnos = Seq( - CorrectVecAnno("vec", enumExampleName, Set()), - CorrectVecAnno("vec_of_vecs", enumExampleName, Set()), - CorrectVecAnno( - "vec_of_bundles", - enumExampleName, - Set(Seq("field"), Seq("vec"), Seq("inner_bundle1", "e"), Seq("inner_bundle1", "v")) - ), - CorrectVecAnno("vec_of_bundles", otherEnumName, Set(Seq("other"))), - CorrectVecAnno("vec_of_bundles", localEnumName, Set(Seq("local"))), - CorrectVecAnno("bund.vec", enumExampleName, Set()), - CorrectVecAnno("bund.inner_bundle1.v", enumExampleName, Set()) - ) - - def printAnnos(annos: Seq[Annotation]) { - println("Enum definitions:") - annos.foreach { - case EnumDefAnnotation(enumTypeName, definition) => println(s"\t$enumTypeName: $definition") - case _ => - } - println("Enum components:") - annos.foreach { - case EnumComponentAnnotation(target, enumTypeName) => println(s"\t$target => $enumTypeName") - case _ => - } - println("Enum vecs:") - annos.foreach { - case EnumVecAnnotation(target, enumTypeName, fields) => println(s"\t$target[$fields] => $enumTypeName") - case _ => - } - } - - def isCorrect(anno: EnumDefAnnotation, correct: CorrectDefAnno): Boolean = { - (anno.typeName == correct.typeName || - anno.typeName.endsWith("." + correct.typeName) || - anno.typeName.endsWith("$" + correct.typeName)) && - anno.definition == correct.definition - } - - def isCorrect(anno: EnumComponentAnnotation, correct: CorrectCompAnno): Boolean = { - (anno.target match { - case ComponentName(name, _) => name == correct.targetName - case _ => throw new Exception("Unknown target type in EnumComponentAnnotation") - }) && - (anno.enumTypeName == correct.typeName || anno.enumTypeName.endsWith("." + correct.typeName) || - anno.enumTypeName.endsWith("$" + correct.typeName)) - } - - def isCorrect(anno: EnumVecAnnotation, correct: CorrectVecAnno): Boolean = { - (anno.target match { - case ComponentName(name, _) => name == correct.targetName - case _ => throw new Exception("Unknown target type in EnumVecAnnotation") - }) && - (anno.typeName == correct.typeName || anno.typeName.endsWith("." + correct.typeName) || - anno.typeName.endsWith("$" + correct.typeName)) && - anno.fields.map(_.toSeq).toSet == correct.fields - } - - def allCorrectDefs(annos: Seq[EnumDefAnnotation], corrects: Seq[CorrectDefAnno]): Boolean = { - corrects.forall(c => annos.exists(isCorrect(_, c))) && - correctDefAnnos.length == annos.length - } - - // Because temporary variables might be formed and annotated, we do not check that every component or vector - // annotation is accounted for in the correct results listed above - def allCorrectComps(annos: Seq[EnumComponentAnnotation], corrects: Seq[CorrectCompAnno]): Boolean = - corrects.forall(c => annos.exists(isCorrect(_, c))) - - def allCorrectVecs(annos: Seq[EnumVecAnnotation], corrects: Seq[CorrectVecAnno]): Boolean = - corrects.forall(c => annos.exists(isCorrect(_, c))) - - def test(strongEnumAnnotatorGen: () => Module) { - val annos = (new ChiselStage).execute( - Array("--target-dir", "test_run_dir", "--no-run-firrtl"), - Seq(ChiselGeneratorAnnotation(strongEnumAnnotatorGen)) - ) - - val enumDefAnnos = annos.collect { case a: EnumDefAnnotation => a } - val enumCompAnnos = annos.collect { case a: EnumComponentAnnotation => a } - val enumVecAnnos = annos.collect { case a: EnumVecAnnotation => a } - - allCorrectDefs(enumDefAnnos, correctDefAnnos) should be(true) - allCorrectComps(enumCompAnnos, correctCompAnnos) should be(true) - allCorrectVecs(enumVecAnnos, correctVecAnnos) should be(true) - - } - - "Test that strong enums annotate themselves appropriately" in { - test(() => new ChiselEnumAnnotator) - test(() => new ChiselEnumAnnotatorWithChiselName) - } -} diff --git a/src/test/scala/chiselTests/ChiselSpec.scala b/src/test/scala/chiselTests/ChiselSpec.scala deleted file mode 100644 index e00afcf6..00000000 --- a/src/test/scala/chiselTests/ChiselSpec.scala +++ /dev/null @@ -1,368 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.aop.Aspect -import chisel3.stage.{ - ChiselGeneratorAnnotation, - ChiselStage, - NoRunFirrtlCompilerAnnotation, - PrintFullStackTraceAnnotation -} -import chisel3.testers._ -import firrtl.annotations.Annotation -import firrtl.ir.Circuit -import firrtl.util.BackendCompilationUtilities -import firrtl.{AnnotationSeq, EmittedVerilogCircuitAnnotation} -import _root_.logger.Logger -import firrtl.stage.FirrtlCircuitAnnotation -import org.scalacheck._ -import org.scalatest._ -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.freespec.AnyFreeSpec -import org.scalatest.funspec.AnyFunSpec -import org.scalatest.propspec.AnyPropSpec -import org.scalatest.matchers.should.Matchers -import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks - -import java.io.{ByteArrayOutputStream, PrintStream} -import java.security.Permission -import scala.reflect.ClassTag - -/** Common utility functions for Chisel unit tests. */ -trait ChiselRunners extends Assertions with BackendCompilationUtilities { - def runTester( - t: => BasicTester, - additionalVResources: Seq[String] = Seq(), - annotations: AnnotationSeq = Seq() - ): Boolean = { - // Change this to enable Treadle as a backend - val defaultBackend = { - val useTreadle = sys.env.get("CHISEL3_CI_USE_TREADLE").isDefined - if (useTreadle) chisel3.testers.TreadleBackend else chisel3.testers.TesterDriver.defaultBackend - } - val hasBackend = TestUtils.containsBackend(annotations) - val annos: Seq[Annotation] = if (hasBackend) annotations else defaultBackend +: annotations - TesterDriver.execute(() => t, additionalVResources, annos) - } - def assertTesterPasses( - t: => BasicTester, - additionalVResources: Seq[String] = Seq(), - annotations: AnnotationSeq = Seq() - ): Unit = { - assert(runTester(t, additionalVResources, annotations)) - } - def assertTesterFails( - t: => BasicTester, - additionalVResources: Seq[String] = Seq(), - annotations: Seq[chisel3.aop.Aspect[_]] = Seq() - ): Unit = { - assert(!runTester(t, additionalVResources, annotations)) - } - - def assertKnownWidth(expected: Int)(gen: => Data): Unit = { - assertTesterPasses(new BasicTester { - val x = gen - assert(x.getWidth === expected) - // Sanity check that firrtl doesn't change the width - x := 0.U.asTypeOf(chiselTypeOf(x)) - val (_, done) = chisel3.util.Counter(true.B, 2) - when(done) { - chisel3.assert(~(x.asUInt) === -1.S(expected.W).asUInt) - stop() - } - }) - } - - def assertInferredWidth(expected: Int)(gen: => Data): Unit = { - assertTesterPasses(new BasicTester { - val x = gen - assert(!x.isWidthKnown, s"Asserting that width should be inferred yet width is known to Chisel!") - x := 0.U.asTypeOf(chiselTypeOf(x)) - val (_, done) = chisel3.util.Counter(true.B, 2) - when(done) { - chisel3.assert(~(x.asUInt) === -1.S(expected.W).asUInt) - stop() - } - }) - } - - /** Compiles a Chisel Module to Verilog - * NOTE: This uses the "test_run_dir" as the default directory for generated code. - * @param t the generator for the module - * @return the Verilog code as a string. - */ - def compile(t: => RawModule): String = { - (new ChiselStage) - .execute( - Array("--target-dir", createTestDirectory(this.getClass.getSimpleName).toString), - Seq(ChiselGeneratorAnnotation(() => t)) - ) - .collectFirst { - case EmittedVerilogCircuitAnnotation(a) => a.value - } - .getOrElse(fail("No Verilog circuit was emitted by the FIRRTL compiler!")) - } - - def elaborateAndGetModule[A <: RawModule](t: => A): A = { - var res: Any = null - ChiselStage.elaborate { - res = t - res.asInstanceOf[A] - } - res.asInstanceOf[A] - } - - /** Compiles a Chisel Module to FIRRTL - * NOTE: This uses the "test_run_dir" as the default directory for generated code. - * @param t the generator for the module - * @return The FIRRTL Circuit and Annotations _before_ FIRRTL compilation - */ - def getFirrtlAndAnnos(t: => RawModule, providedAnnotations: Seq[Annotation] = Nil): (Circuit, Seq[Annotation]) = { - val args = Array( - "--target-dir", - createTestDirectory(this.getClass.getSimpleName).toString, - "--no-run-firrtl", - "--full-stacktrace" - ) - val annos = (new ChiselStage).execute(args, Seq(ChiselGeneratorAnnotation(() => t)) ++ providedAnnotations) - val circuit = annos.collectFirst { - case FirrtlCircuitAnnotation(c) => c - }.getOrElse(fail("No FIRRTL Circuit found!!")) - (circuit, annos) - } -} - -/** Spec base class for BDD-style testers. */ -abstract class ChiselFlatSpec extends AnyFlatSpec with ChiselRunners with Matchers - -/** Spec base class for BDD-style testers. */ -abstract class ChiselFreeSpec extends AnyFreeSpec with ChiselRunners with Matchers - -/** Spec base class for BDD-style testers. */ -abstract class ChiselFunSpec extends AnyFunSpec with ChiselRunners with Matchers - -/** Spec base class for property-based testers. */ -abstract class ChiselPropSpec extends AnyPropSpec with ChiselRunners with ScalaCheckPropertyChecks with Matchers { - - // Constrain the default number of instances generated for every use of forAll. - implicit override val generatorDrivenConfig: PropertyCheckConfiguration = - PropertyCheckConfiguration(minSuccessful = 8, minSize = 1, sizeRange = 3) - - // Generator for small positive integers. - val smallPosInts = Gen.choose(1, 4) - - // Generator for positive (ascending or descending) ranges. - def posRange: Gen[Range] = for { - dir <- Gen.oneOf(true, false) - step <- Gen.choose(1, 3) - m <- Gen.choose(1, 10) - n <- Gen.choose(1, 10) - } yield { - if (dir) { - Range(m, (m + n) * step, step) - } else { - Range((m + n) * step, m, -step) - } - } - - // Generator for widths considered "safe". - val safeUIntWidth = Gen.choose(1, 30) - - // Generators for integers that fit within "safe" widths. - val safeUInts = Gen.choose(0, (1 << 30)) - - // Generators for vector sizes. - val vecSizes = Gen.choose(0, 4) - - // Generator for string representing an arbitrary integer. - val binaryString = for (i <- Arbitrary.arbitrary[Int]) yield "b" + i.toBinaryString - - // Generator for a sequence of Booleans of size n. - def enSequence(n: Int): Gen[List[Boolean]] = Gen.containerOfN[List, Boolean](n, Gen.oneOf(true, false)) - - // Generator which gives a width w and a list (of size n) of numbers up to w bits. - def safeUIntN(n: Int): Gen[(Int, List[Int])] = for { - w <- smallPosInts - i <- Gen.containerOfN[List, Int](n, Gen.choose(0, (1 << w) - 1)) - } yield (w, i) - - // Generator which gives a width w and a numbers up to w bits. - val safeUInt = for { - w <- smallPosInts - i <- Gen.choose(0, (1 << w) - 1) - } yield (w, i) - - // Generator which gives a width w and a list (of size n) of a pair of numbers up to w bits. - def safeUIntPairN(n: Int): Gen[(Int, List[(Int, Int)])] = for { - w <- smallPosInts - i <- Gen.containerOfN[List, Int](n, Gen.choose(0, (1 << w) - 1)) - j <- Gen.containerOfN[List, Int](n, Gen.choose(0, (1 << w) - 1)) - } yield (w, i.zip(j)) - - // Generator which gives a width w and a pair of numbers up to w bits. - val safeUIntPair = for { - w <- smallPosInts - i <- Gen.choose(0, (1 << w) - 1) - j <- Gen.choose(0, (1 << w) - 1) - } yield (w, i, j) -} - -trait Utils { - - /** Run some Scala thunk and return STDOUT and STDERR as strings. - * @param thunk some Scala code - * @return a tuple containing STDOUT, STDERR, and what the thunk returns - */ - def grabStdOutErr[T](thunk: => T): (String, String, T) = { - val stdout, stderr = new ByteArrayOutputStream() - val ret = scala.Console.withOut(stdout) { scala.Console.withErr(stderr) { thunk } } - (stdout.toString, stderr.toString, ret) - } - - /** Run some Scala thunk and return all logged messages as Strings - * @param thunk some Scala code - * @return a tuple containing LOGGED, and what the thunk returns - */ - def grabLog[T](thunk: => T): (String, T) = { - val baos = new ByteArrayOutputStream() - val stream = new PrintStream(baos, true, "utf-8") - val ret = Logger.makeScope(Nil) { - Logger.setOutput(stream) - thunk - } - (baos.toString, ret) - } - - /** Encodes a System.exit exit code - * @param status the exit code - */ - private case class ExitException(status: Int) extends SecurityException(s"Found a sys.exit with code $status") - - /** A security manager that converts calls to System.exit into [[ExitException]]s by explicitly disabling the ability of - * a thread to actually exit. For more information, see: - * - https://docs.oracle.com/javase/tutorial/essential/environment/security.html - */ - private class ExceptOnExit extends SecurityManager { - override def checkPermission(perm: Permission): Unit = {} - override def checkPermission(perm: Permission, context: Object): Unit = {} - override def checkExit(status: Int): Unit = { - super.checkExit(status) - throw ExitException(status) - } - } - - /** Encodes a file that some code tries to write to - * @param the file name - */ - private case class WriteException(file: String) extends SecurityException(s"Tried to write to file $file") - - /** A security manager that converts writes to any file into [[WriteException]]s. - */ - private class ExceptOnWrite extends SecurityManager { - override def checkPermission(perm: Permission): Unit = {} - override def checkPermission(perm: Permission, context: Object): Unit = {} - override def checkWrite(file: String): Unit = { - super.checkWrite(file) - throw WriteException(file) - } - } - - /** Run some Scala code (a thunk) in an environment where all System.exit are caught and returned. This avoids a - * situation where a test results in something actually exiting and killing the entire test. This is necessary if you - * want to test a command line program, e.g., the `main` method of [[firrtl.options.Stage Stage]]. - * - * NOTE: THIS WILL NOT WORK IN SITUATIONS WHERE THE THUNK IS CATCHING ALL [[Exception]]s OR [[Throwable]]s, E.G., - * SCOPT. IF THIS IS HAPPENING THIS WILL NOT WORK. REPEAT THIS WILL NOT WORK. - * @param thunk some Scala code - * @return either the output of the thunk (`Right[T]`) or an exit code (`Left[Int]`) - */ - def catchStatus[T](thunk: => T): Either[Int, T] = { - try { - System.setSecurityManager(new ExceptOnExit()) - Right(thunk) - } catch { - case ExitException(a) => Left(a) - } finally { - System.setSecurityManager(null) - } - } - - /** Run some Scala code (a thunk) in an environment where file writes are caught and the file that a program tries to - * write to is returned. This is useful if you want to test that some thunk either tries to write to a specific file - * or doesn't try to write at all. - */ - def catchWrites[T](thunk: => T): Either[String, T] = { - throw new Exception("Do not use, not thread-safe") - try { - System.setSecurityManager(new ExceptOnWrite()) - Right(thunk) - } catch { - case WriteException(a) => Left(a) - } finally { - System.setSecurityManager(null) - } - } - - /** A tester which runs generator and uses an aspect to check the returned object - * @param gen function to generate a Chisel module - * @param f a function to check the Chisel module - * @tparam T the Chisel module class - */ - def aspectTest[T <: RawModule](gen: () => T)(f: T => Unit)(implicit scalaMajorVersion: Int): Unit = { - // Runs chisel stage - def run[T <: RawModule](gen: () => T, annotations: AnnotationSeq): AnnotationSeq = { - new ChiselStage().run( - Seq(ChiselGeneratorAnnotation(gen), NoRunFirrtlCompilerAnnotation, PrintFullStackTraceAnnotation) ++ annotations - ) - } - // Creates a wrapping aspect to contain checking function - case object BuiltAspect extends Aspect[T] { - override def toAnnotation(top: T): AnnotationSeq = { f(top); Nil } - } - val currentMajorVersion = scala.util.Properties.versionNumberString.split('.')(1).toInt - if (currentMajorVersion >= scalaMajorVersion) { - run(gen, Seq(BuiltAspect)) - } - } - - /** Run some code and rethrow an exception with a specific type if an exception of that type occurs anywhere in the - * stack trace. - * - * This is useful for "extracting" one exception that may be wrapped by other exceptions. - * - * Example usage: - * {{{ - * a [ChiselException] should be thrownBy extractCause[ChiselException] { /* ... */ } - * }}} - * - * @param thunk some code to run - * @tparam A the type of the exception to extract - * @return nothing - */ - def extractCause[A <: Throwable: ClassTag](thunk: => Any): Unit = { - def unrollCauses(a: Throwable): Seq[Throwable] = a match { - case null => Seq.empty - case _ => a +: unrollCauses(a.getCause) - } - - val exceptions: Seq[_ <: Throwable] = - try { - thunk - Seq.empty - } catch { - case a: Throwable => unrollCauses(a) - } - - exceptions.collectFirst { case a: A => a } match { - case Some(a) => throw a - case None => - exceptions match { - case Nil => () - case h :: t => throw h - } - } - - } -} diff --git a/src/test/scala/chiselTests/ChiselTestUtilitiesSpec.scala b/src/test/scala/chiselTests/ChiselTestUtilitiesSpec.scala deleted file mode 100644 index 451ba885..00000000 --- a/src/test/scala/chiselTests/ChiselTestUtilitiesSpec.scala +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import org.scalatest.exceptions.TestFailedException - -class ChiselTestUtilitiesSpec extends ChiselFlatSpec { - // Who tests the testers? - "assertKnownWidth" should "error when the expected width is wrong" in { - intercept[TestFailedException] { - assertKnownWidth(7) { - Wire(UInt(8.W)) - } - } - } - - it should "error when the width is unknown" in { - intercept[ChiselException] { - assertKnownWidth(7) { - Wire(UInt()) - } - } - } - - it should "work if the width is correct" in { - assertKnownWidth(8) { - Wire(UInt(8.W)) - } - } - - "assertInferredWidth" should "error if the width is known" in { - intercept[TestFailedException] { - assertInferredWidth(8) { - Wire(UInt(8.W)) - } - } - } - - it should "error if the expected width is wrong" in { - a[TestFailedException] shouldBe thrownBy { - assertInferredWidth(8) { - val w = Wire(UInt()) - w := 2.U(2.W) - w - } - } - } - - it should "pass if the width is correct" in { - assertInferredWidth(4) { - val w = Wire(UInt()) - w := 2.U(4.W) - w - } - } -} diff --git a/src/test/scala/chiselTests/Clock.scala b/src/test/scala/chiselTests/Clock.scala deleted file mode 100644 index c28e1344..00000000 --- a/src/test/scala/chiselTests/Clock.scala +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.testers.BasicTester - -class ClockAsUIntTester extends BasicTester { - assert(true.B.asClock.asUInt === 1.U) - assert(true.B.asClock.asBool === true.B) - stop() -} - -class WithClockAndNoReset extends RawModule { - val clock1 = IO(Input(Clock())) - val clock2 = IO(Input(Clock())) - val in = IO(Input(Bool())) - val out = IO(Output(Bool())) - val a = withClock(clock2) { - RegNext(in) - } - - out := a -} - -class ClockSpec extends ChiselPropSpec { - property("Bool.asClock.asUInt should pass a signal through unaltered") { - assertTesterPasses { new ClockAsUIntTester } - } - - property("Should be able to use withClock in a module with no reset") { - val circuit = ChiselStage.emitChirrtl(new WithClockAndNoReset) - circuit.contains("reg a : UInt<1>, clock2") should be(true) - } -} diff --git a/src/test/scala/chiselTests/CloneModuleSpec.scala b/src/test/scala/chiselTests/CloneModuleSpec.scala deleted file mode 100644 index 4a70db85..00000000 --- a/src/test/scala/chiselTests/CloneModuleSpec.scala +++ /dev/null @@ -1,155 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.util.{log2Ceil, Decoupled, DeqIO, EnqIO, Queue, QueueIO} -import chisel3.experimental.{CloneModuleAsRecord, IO} -import chisel3.testers.BasicTester - -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))) - val deq = IO(Flipped(DeqIO(gen))) - val count = IO(Output(UInt(log2Ceil(entries + 1).W))) - val impl = withClockAndReset(clk, rst) { Module(new Queue(gen, entries)) } - impl.io.enq <> enq - deq <> impl.io.deq - count := impl.io.count -} - -class QueueClone(multiIO: Boolean = false) extends Module { - val io = IO(new QueueIO(UInt(32.W), 4)) - if (multiIO) { - val q1 = Module(new MultiIOQueue(UInt(32.W), 2)) - val q2_io = CloneModuleAsRecord(q1) - q1.clk := clock - q1.rst := reset - q1.enq <> io.enq - q2_io("clk").asInstanceOf[Clock] := clock - q2_io("rst").asInstanceOf[Reset] := reset - q2_io("enq").asInstanceOf[q1.enq.type] <> q1.deq - io.deq <> q2_io("deq").asInstanceOf[q1.deq.type] - io.count := q1.count + q2_io("count").asInstanceOf[q1.count.type] - } else { - val q1 = Module(new Queue(UInt(32.W), 2)) - val q2_io = CloneModuleAsRecord(q1) - q1.io.enq <> io.enq - val q2_io_bundle = q2_io("io").asInstanceOf[q1.io.type] - q2_io_bundle.enq <> q1.io.deq - io.deq <> q2_io_bundle.deq - io.count := q1.io.count + q2_io_bundle.count - } -} - -class QueueCloneTester(x: Int, multiIO: Boolean = false) extends BasicTester { - val dut = Module(new QueueClone(multiIO)) - val start = RegNext(dut.io.enq.fire, true.B) - val accept = RegNext(dut.io.deq.valid, false.B) - dut.io.enq.bits := x.U - dut.io.enq.valid := start - dut.io.deq.ready := accept - when(dut.io.deq.fire) { - assert(dut.io.deq.bits === x.U) - stop() - } -} - -class CloneModuleAsRecordAnnotate extends Module { - override def desiredName = "Top" - val in = IO(Flipped(Decoupled(UInt(8.W)))) - val out = IO(Decoupled(UInt(8.W))) - - val q1 = Module(new Queue(UInt(8.W), 4)) - val q2 = CloneModuleAsRecord(q1) - val q2_io = q2("io").asInstanceOf[q1.io.type] - // Also make a wire to check that cloning works, can be connected to, and annotated - val q2_wire = { - val w = Wire(chiselTypeOf(q2)) - w <> q2 - w - } - // But connect to the original (using last connect semantics to override connects to wire - q1.io.enq <> in - q2_io.enq <> q1.io.deq - out <> q2_io.deq -} - -class CloneModuleSpec extends ChiselPropSpec { - - val xVals = Table( - ("x"), // First tuple defines column names - (42), // Subsequent tuples define the data - (63), - (99) - ) - - property("QueueCloneTester should return the correct result") { - forAll(xVals) { (x: Int) => - assertTesterPasses { new QueueCloneTester(x) } - } - } - - property("QueueClone's cloned queues should share the same module") { - val c = ChiselStage.convert(new QueueClone) - assert(c.modules.length == 2) - } - - property("Clone of MultiIOModule should simulate correctly") { - forAll(xVals) { (x: Int) => - assertTesterPasses { new QueueCloneTester(x, multiIO = true) } - } - } - - property("Clones of MultiIOModules should share the same module") { - val c = ChiselStage.convert(new QueueClone(multiIO = true)) - assert(c.modules.length == 3) - } - - property("Cloned Modules should annotate correctly") { - // Hackily get the actually Module object out - var mod: CloneModuleAsRecordAnnotate = null - val res = ChiselStage.convert { - mod = new CloneModuleAsRecordAnnotate - mod - } - // ********** Checking the output of CloneModuleAsRecord ********** - // Note that we overrode desiredName so that Top is named "Top" - mod.q1.io.enq.toTarget.serialize should be("~Top|Queue>io.enq") - mod.q2_io.deq.toTarget.serialize should be("~Top|Queue>io.deq") - mod.q1.io.enq.toAbsoluteTarget.serialize should be("~Top|Top/q1:Queue>io.enq") - mod.q2_io.deq.toAbsoluteTarget.serialize should be("~Top|Top/q2:Queue>io.deq") - // Legacy APIs that nevertheless were tricky to get right - mod.q1.io.enq.toNamed.serialize should be("Top.Queue.io.enq") - mod.q2_io.deq.toNamed.serialize should be("Top.Queue.io.deq") - mod.q1.io.enq.instanceName should be("io.enq") - mod.q2_io.deq.instanceName should be("io.deq") - mod.q1.io.enq.pathName should be("Top.q1.io.enq") - mod.q2_io.deq.pathName should be("Top.q2.io.deq") - mod.q1.io.enq.parentPathName should be("Top.q1") - mod.q2_io.deq.parentPathName should be("Top.q2") - mod.q1.io.enq.parentModName should be("Queue") - mod.q2_io.deq.parentModName should be("Queue") - - // ********** Checking the wire cloned from the output of CloneModuleAsRecord ********** - val wire_io = mod.q2_wire("io").asInstanceOf[QueueIO[UInt]] - mod.q2_wire.toTarget.serialize should be("~Top|Top>q2_wire") - wire_io.enq.toTarget.serialize should be("~Top|Top>q2_wire.io.enq") - mod.q2_wire.toAbsoluteTarget.serialize should be("~Top|Top>q2_wire") - wire_io.enq.toAbsoluteTarget.serialize should be("~Top|Top>q2_wire.io.enq") - // Legacy APIs - mod.q2_wire.toNamed.serialize should be("Top.Top.q2_wire") - wire_io.enq.toNamed.serialize should be("Top.Top.q2_wire.io.enq") - mod.q2_wire.instanceName should be("q2_wire") - wire_io.enq.instanceName should be("q2_wire.io.enq") - mod.q2_wire.pathName should be("Top.q2_wire") - wire_io.enq.pathName should be("Top.q2_wire.io.enq") - mod.q2_wire.parentPathName should be("Top") - wire_io.enq.parentPathName should be("Top") - mod.q2_wire.parentModName should be("Top") - wire_io.enq.parentModName should be("Top") - } - -} diff --git a/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala b/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala deleted file mode 100644 index d388c093..00000000 --- a/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala +++ /dev/null @@ -1,820 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import scala.collection.immutable.ListMap -import chisel3.stage.ChiselStage.emitChirrtl - -// Keep Chisel._ separate from chisel3._ below -object CompatibilityComponents { - import Chisel._ - import Chisel3Components._ - - class ChiselBundle extends Bundle { - val a = UInt(width = 32) - val b = UInt(width = 32).flip - } - class ChiselRecord extends Record { - val elements = ListMap("a" -> UInt(width = 32), "b" -> UInt(width = 32).flip) - override def cloneType: this.type = (new ChiselRecord).asInstanceOf[this.type] - } - - abstract class ChiselDriverModule(_io: => Record) extends Module { - val io = _io - io.elements("a").asUInt := UInt(123) - assert(io.elements("b").asUInt === UInt(123)) - } - abstract class ChiselPassthroughModule(_io: => Record) extends Module { - val io = _io - io.elements("b").asUInt := io.elements("a").asUInt - } - - class ChiselBundleModuleA extends ChiselDriverModule(new ChiselBundle) - class ChiselBundleModuleB extends ChiselPassthroughModule((new ChiselBundle).flip) - class ChiselRecordModuleA extends ChiselDriverModule(new ChiselRecord) - class ChiselRecordModuleB extends ChiselPassthroughModule((new ChiselRecord).flip) - - class ChiselModuleChisel3BundleA extends ChiselDriverModule(new Chisel3Bundle) - class ChiselModuleChisel3BundleB extends ChiselPassthroughModule((new Chisel3Bundle).flip) - class ChiselModuleChisel3RecordA extends ChiselDriverModule(new Chisel3Record) - class ChiselModuleChisel3RecordB extends ChiselPassthroughModule((new Chisel3Record).flip) -} - -object Chisel3Components { - import chisel3._ - import CompatibilityComponents._ - - class Chisel3Bundle extends Bundle { - val a = Output(UInt(32.W)) - val b = Input(UInt(32.W)) - } - - class Chisel3Record extends Record { - val elements = ListMap("a" -> Output(UInt(32.W)), "b" -> Input(UInt(32.W))) - override def cloneType: this.type = (new Chisel3Record).asInstanceOf[this.type] - } - - abstract class Chisel3DriverModule(_io: => Record) extends Module { - val io = IO(_io) - io.elements("a").asUInt := 123.U - assert(io.elements("b").asUInt === 123.U) - } - abstract class Chisel3PassthroughModule(_io: => Record) extends Module { - val io = IO(_io) - io.elements("b").asUInt := io.elements("a").asUInt - } - - class Chisel3BundleModuleA extends Chisel3DriverModule(new Chisel3Bundle) - class Chisel3BundleModuleB extends Chisel3PassthroughModule(Flipped(new Chisel3Bundle)) - class Chisel3RecordModuleA extends Chisel3DriverModule(new Chisel3Record) - class Chisel3RecordModuleB extends Chisel3PassthroughModule(Flipped(new Chisel3Record)) - - class Chisel3ModuleChiselBundleA extends Chisel3DriverModule(new ChiselBundle) - class Chisel3ModuleChiselBundleB extends Chisel3PassthroughModule(Flipped(new ChiselBundle)) - class Chisel3ModuleChiselRecordA extends Chisel3DriverModule(new ChiselRecord) - class Chisel3ModuleChiselRecordB extends Chisel3PassthroughModule(Flipped(new ChiselRecord)) -} - -class CompatibilityInteroperabilitySpec extends ChiselFlatSpec { - - "Modules defined in the Chisel._" should "successfully bulk connect in chisel3._" in { - import chisel3._ - import chisel3.testers.BasicTester - import CompatibilityComponents._ - - assertTesterPasses(new BasicTester { - val a = Module(new ChiselBundleModuleA) - val b = Module(new ChiselBundleModuleB) - b.io <> a.io - stop() - }) - assertTesterPasses(new BasicTester { - val a = Module(new ChiselRecordModuleA) - val b = Module(new ChiselRecordModuleB) - b.io <> a.io - stop() - }) - } - - "Moduless defined in the chisel3._" should "successfully bulk connect in Chisel._" in { - import Chisel._ - import chisel3.testers.BasicTester - import Chisel3Components._ - - assertTesterPasses(new BasicTester { - val a = Module(new Chisel3BundleModuleA) - val b = Module(new Chisel3BundleModuleB) - b.io <> a.io - stop() - }) - assertTesterPasses(new BasicTester { - val a = Module(new Chisel3RecordModuleA) - val b = Module(new Chisel3RecordModuleB) - b.io <> a.io - stop() - }) - } - - "Bundles defined in Chisel._" should "work in chisel3._ Modules" in { - import chisel3._ - import chisel3.testers.BasicTester - import Chisel3Components._ - - assertTesterPasses(new BasicTester { - val a = Module(new Chisel3ModuleChiselBundleA) - val b = Module(new Chisel3ModuleChiselBundleB) - b.io <> a.io - stop() - }) - assertTesterPasses(new BasicTester { - val a = Module(new Chisel3ModuleChiselRecordA) - val b = Module(new Chisel3ModuleChiselRecordB) - b.io <> a.io - stop() - }) - } - - "Bundles defined in chisel3._" should "work in Chisel._ Modules" in { - import chisel3._ - import chisel3.testers.BasicTester - import CompatibilityComponents._ - - assertTesterPasses(new BasicTester { - val a = Module(new ChiselModuleChisel3BundleA) - val b = Module(new ChiselModuleChisel3BundleB) - b.io <> a.io - stop() - }) - assertTesterPasses(new BasicTester { - val a = Module(new ChiselModuleChisel3RecordA) - val b = Module(new ChiselModuleChisel3RecordB) - b.io <> a.io - stop() - }) - } - - "Similar Bundles defined in the chisel3._ and Chisel._" should - "successfully bulk connect in chisel3._" in { - import chisel3._ - import chisel3.testers.BasicTester - import Chisel3Components._ - import CompatibilityComponents._ - - assertTesterPasses(new BasicTester { - val a = Module(new ChiselBundleModuleA) - val b = Module(new Chisel3BundleModuleB) - b.io <> a.io - stop() - }) - assertTesterPasses(new BasicTester { - val a = Module(new Chisel3BundleModuleA) - val b = Module(new ChiselBundleModuleB) - b.io <> a.io - stop() - }) - assertTesterPasses(new BasicTester { - val a = Module(new ChiselRecordModuleA) - val b = Module(new Chisel3RecordModuleB) - b.io <> a.io - stop() - }) - assertTesterPasses(new BasicTester { - val a = Module(new Chisel3RecordModuleA) - val b = Module(new ChiselRecordModuleB) - b.io <> a.io - stop() - }) - } - they should "successfully bulk connect in Chisel._" in { - import Chisel._ - import chisel3.testers.BasicTester - import Chisel3Components._ - import CompatibilityComponents._ - - assertTesterPasses(new BasicTester { - val a = Module(new ChiselBundleModuleA) - val b = Module(new Chisel3BundleModuleB) - b.io <> a.io - stop() - }) - assertTesterPasses(new BasicTester { - val a = Module(new Chisel3BundleModuleA) - val b = Module(new ChiselBundleModuleB) - b.io <> a.io - stop() - }) - assertTesterPasses(new BasicTester { - val a = Module(new ChiselRecordModuleA) - val b = Module(new Chisel3RecordModuleB) - b.io <> a.io - stop() - }) - assertTesterPasses(new BasicTester { - val a = Module(new Chisel3RecordModuleA) - val b = Module(new ChiselRecordModuleB) - b.io <> a.io - stop() - }) - } - - "An instance of a chisel3.Module inside a Chisel.Module" should "have its inputs invalidated" in { - compile { - import Chisel._ - new Module { - val io = new Bundle { - val in = UInt(INPUT, width = 32) - val cond = Bool(INPUT) - val out = UInt(OUTPUT, width = 32) - } - val children = - Seq(Module(new PassthroughModule), Module(new PassthroughMultiIOModule), Module(new PassthroughRawModule)) - io.out := children.map(_.io.out).reduce(_ + _) - children.foreach { child => - when(io.cond) { - child.io.in := io.in - } - } - } - } - } - - "Compatibility Modules" should "have Bool as their reset type" in { - compile { - import Chisel._ - class Intf extends Bundle { - val in = Bool(INPUT) - val en = Bool(INPUT) - val out = Bool(OUTPUT) - } - class Child extends Module { - val io = new Intf - io.out := Mux(io.en, io.in, reset) - } - new Module { - val io = new Intf - val child = Module(new Child) - io <> child.io - } - } - } - - "Compatibility Modules" should "be instantiable inside chisel3 Modules" in { - compile { - object Compat { - import Chisel._ - class Intf extends Bundle { - val in = Input(UInt(8.W)) - val out = Output(UInt(8.W)) - } - class OldMod extends Module { - val io = IO(new Intf) - io.out := Reg(next = io.in) - } - } - import chisel3._ - import Compat._ - new Module { - val io = IO(new Intf) - io <> Module(new Module { - val io = IO(new Intf) - val inst = Module(new OldMod) - io <> inst.io - }).io - } - } - } - - "A chisel3 Bundle that instantiates a Chisel Bundle" should "bulk connect correctly" in { - compile { - object Compat { - import Chisel._ - class BiDir extends Bundle { - val a = Input(UInt(8.W)) - val b = Output(UInt(8.W)) - } - class Struct extends Bundle { - val a = UInt(8.W) - } - } - import chisel3._ - import Compat._ - class Bar extends Bundle { - val bidir1 = new BiDir - val bidir2 = Flipped(new BiDir) - val struct1 = Output(new Struct) - val struct2 = Input(new Struct) - } - // Check every connection both ways to see that chisel3 <>'s commutativity holds - class Child extends RawModule { - val deq = IO(new Bar) - val enq = IO(Flipped(new Bar)) - enq <> deq - deq <> enq - } - new RawModule { - val deq = IO(new Bar) - val enq = IO(Flipped(new Bar)) - // Also important to check connections to child ports - val c1 = Module(new Child) - val c2 = Module(new Child) - c1.enq <> enq - enq <> c1.enq - c2.enq <> c1.deq - c1.deq <> c2.enq - deq <> c2.deq - c2.deq <> deq - } - } - } - - "A unidirectional but flipped Bundle" should "bulk connect in import chisel3._ code correctly" in { - object Compat { - import Chisel._ - class MyBundle(extraFlip: Boolean) extends Bundle { - private def maybeFlip[T <: Data](t: T): T = if (extraFlip) t.flip else t - val foo = maybeFlip(new Bundle { - val bar = UInt(INPUT, width = 8) - }) - } - } - import chisel3._ - import Compat._ - class Top(extraFlip: Boolean) extends RawModule { - val port = IO(new MyBundle(extraFlip)) - val wire = Wire(new MyBundle(extraFlip)) - port <> DontCare - wire <> DontCare - port <> wire - wire <> port - port.foo <> wire.foo - wire.foo <> port.foo - } - compile(new Top(true)) - compile(new Top(false)) - } - - "A unidirectional but flipped Bundle with something close to NotStrict compileOptions, but not exactly" should "bulk connect in import chisel3._ code correctly" in { - object Compat { - import Chisel.{defaultCompileOptions => _, _} - // arbitrary thing to make this *not* exactly NotStrict - implicit val defaultCompileOptions = new chisel3.ExplicitCompileOptions.CompileOptionsClass( - connectFieldsMustMatch = false, - declaredTypeMustBeUnbound = false, - dontTryConnectionsSwapped = false, - dontAssumeDirectionality = false, - checkSynthesizable = false, - explicitInvalidate = false, - inferModuleReset = true // different from NotStrict, to ensure case class equivalence to NotStrict is false - ) { - override def emitStrictConnects = false - } - - class MyBundle(extraFlip: Boolean) extends Bundle { - private def maybeFlip[T <: Data](t: T): T = if (extraFlip) t.flip else t - val foo = maybeFlip(new Bundle { - val bar = UInt(INPUT, width = 8) - }) - } - } - import chisel3._ - import Compat.{defaultCompileOptions => _, _} - class Top(extraFlip: Boolean) extends RawModule { - val port = IO(new MyBundle(extraFlip)) - val wire = Wire(new MyBundle(extraFlip)) - port <> DontCare - wire <> DontCare - port <> wire - wire <> port - port.foo <> wire.foo - wire.foo <> port.foo - } - compile(new Top(true)) - compile(new Top(false)) - } - - "A Chisel.Bundle with only unspecified directions" should "work with D/I" in { - - object Compat { - import Chisel._ - import chisel3.experimental.hierarchy.{instantiable, public} - - class CompatBiDirUnspecifiedBundle extends Bundle { - val out = Bool() - val in = Flipped(Bool()) - } - - @instantiable - class CompatModule extends Module { - @public val io = IO(new CompatBiDirUnspecifiedBundle) - } - } - - object Chisel3 { - import chisel3._ - import chisel3.experimental.hierarchy.Instance - class Example extends Module { - val mod = Module(new Compat.CompatModule()) - mod.io.in <> DontCare - val inst = Instance(mod.toDefinition) - inst.io.in <> mod.io.out - mod.io.in <> inst.io.out - } - } - compile(new Chisel3.Example) - } - - "A Chisel.Bundle with mixed Specified and Unspecified directions" should "work with D/I" in { - - object Compat { - import Chisel._ - import chisel3.experimental.hierarchy.{instantiable, public} - - class CompatBiDirMixedBundle extends Bundle { - val out = Bool() - val in = Flipped(Bool()) - val explicit = Output(Bool()) - } - - @instantiable - class CompatModule extends Module { - @public val io = IO(new CompatBiDirMixedBundle) - } - } - - object Chisel3 { - import chisel3._ - import chisel3.experimental.hierarchy.Instance - class Example extends Module { - val mod = Module(new Compat.CompatModule) - mod.io.in <> DontCare - val inst = Instance(mod.toDefinition) - inst.io.in <> mod.io.out - mod.io.in <> inst.io.out - } - } - compile(new Chisel3.Example) - } - - "A Chisel.Bundle with only unspecified vec direction" should "work with D/I" in { - - object Compat { - import Chisel._ - import chisel3.experimental.hierarchy.{instantiable, public} - - class CompatBiDirUnspecifiedVecBundle extends Bundle { - val out = Vec(3, Bool()) - val in = Flipped(Vec(3, Bool())) - } - - @instantiable - class CompatModule extends Module { - @public val io = IO(new CompatBiDirUnspecifiedVecBundle) - } - } - - object Chisel3 { - import chisel3._ - import chisel3.experimental.hierarchy.Instance - class Example extends Module { - val mod = Module(new Compat.CompatModule()) - mod.io.in <> DontCare - val inst = Instance(mod.toDefinition) - inst.io.in <> mod.io.out - mod.io.in <> inst.io.out - } - } - compile(new Chisel3.Example) - } - - "A chisel3.Bundle with only unspecified directions" should "work with D/I" in { - - object Chisel3 { - import chisel3._ - import chisel3.experimental.hierarchy.{instantiable, public, Instance} - - class BiDirUnspecifiedBundle extends Bundle { - val out = Bool() - val in = Flipped(Bool()) - } - - @instantiable - class MyModule extends Module { - @public val io = IO(new BiDirUnspecifiedBundle) - io <> DontCare - } - - class Example extends Module { - val mod = Module(new MyModule()) - mod.io.in <> DontCare - val inst = Instance(mod.toDefinition) - inst.io.in <> mod.io.out - mod.io.in <> inst.io.out - } - } - compile(new Chisel3.Example) - } - - "A chisel3.Bundle with mixed Specified and Unspecified directions" should "work with D/I" in { - - object Chisel3 { - import chisel3._ - import chisel3.experimental.hierarchy.{instantiable, public, Instance} - - class BiDirMixedBundle extends Bundle { - val out = Bool() - val in = Flipped(Bool()) - val explicit = Output(Bool()) - } - - @instantiable - class MyModule extends Module { - @public val io = IO(new BiDirMixedBundle) - io <> DontCare - } - class Example extends Module { - val mod = Module(new MyModule) - mod.io.in <> DontCare - val inst = Instance(mod.toDefinition) - inst.io.in <> mod.io.out - mod.io.in <> inst.io.out - } - } - compile(new Chisel3.Example) - } - - "A chisel3.Bundle with only unspecified vec direction" should "work with D/I" in { - - object Chisel3 { - import chisel3._ - import chisel3.experimental.hierarchy.{instantiable, public, Instance} - - class BiDirUnspecifiedVecBundle extends Bundle { - val out = Vec(3, Bool()) - val in = Flipped(Vec(3, Bool())) - } - - @instantiable - class MyModule extends Module { - @public val io = IO(new BiDirUnspecifiedVecBundle) - io <> DontCare - } - - class Example extends Module { - val mod = Module(new MyModule()) - mod.io.in <> DontCare - val inst = Instance(mod.toDefinition) - inst.io.in <> mod.io.out - mod.io.in <> inst.io.out - } - } - compile(new Chisel3.Example) - } - - "A chisel3.Bundle with only unspecified vec direction within an unspecified direction parent Bundle" should "work with D/I" in { - - object Chisel3 { - import chisel3._ - import chisel3.experimental.hierarchy.{instantiable, public, Instance} - - class UnspecifiedVecBundle extends Bundle { - val vec = Vec(3, Bool()) - } - - class UnspecifiedParentBundle extends Bundle { - val out = new UnspecifiedVecBundle - } - - @instantiable - class MyModule extends Module { - @public val io = IO(new UnspecifiedParentBundle) - io <> DontCare - } - - class Example extends Module { - val mod = Module(new MyModule()) - - val wire = Wire(new UnspecifiedParentBundle) - wire.out.vec <> mod.io.out.vec - val inst = Instance(mod.toDefinition) - wire.out.vec <> inst.io.out.vec - - } - } - compile(new Chisel3.Example) - } - - "A undirectioned Chisel.Bundle used in a MixedVec " should "bulk connect in import chisel3._ code correctly" in { - - object Compat { - - import Chisel._ - import chisel3.util.MixedVec - - class ChiselModule extends Module { - val io = IO(new Bundle { - val out = MixedVec(Seq.fill(3) { Bool() }) - val in = Flipped(MixedVec(Seq.fill(3) { Bool() })) - }) - io.out := RegNext(io.in) - } - - } - object Chisel3 { - import chisel3._ - - class Chisel3Module extends Compat.ChiselModule - - class Example extends Module { - val oldMod = Module(new Compat.ChiselModule) - val newMod = Module(new Chisel3Module) - - oldMod.io.in <> DontCare - newMod.io.in <> DontCare - - } - } - compile(new Chisel3.Example) - } - - "A undirectioned Chisel.Bundle with Records with undirectioned and directioned fields " should "work" in { - - object Compat { - - import Chisel._ - - class ChiselModule(gen: () => Data) extends Module { - val io = IO(new Bundle { - val mixed = new Chisel3.MyRecord(gen) - }) - } - - } - object Chisel3 { - import chisel3._ - import scala.collection.immutable.SeqMap - - class MyRecord(gen: () => Data) extends Record with chisel3.experimental.AutoCloneType { - val elements = SeqMap("genDirectioned" -> Output(gen()), "genUndirectioned" -> gen()) - } - - class Example extends Module { - val newMod = Module(new Compat.ChiselModule(() => Bool())) - } - } - compile(new Chisel3.Example) - } - - "A BlackBox with Chisel._ fields in its IO" should "bulk connect in import chisel3._ code correctly" in { - object Compat { - import Chisel._ - class LegacyChiselIO extends Bundle { - val foo = Output(Bool()) - val bar = Output(Bool()) - } - } - object Chisel3 { - import chisel3._ - import chisel3.util.Valid - - class FooModuleIO extends Bundle { - val quz = Input(new QuzIO) - val foo = Output(Bool()) - val bar = Input(Bool()) - } - class QuzIO extends Bundle { - val q = Flipped(Valid(new Compat.LegacyChiselIO)) - } - class FooModule extends Module { - val io = IO(new FooModuleIO) - io <> DontCare - } - class FooMirrorBlackBox extends BlackBox { - val io = IO(Flipped(new FooModuleIO)) - } - class Top extends Module { - val foo = Module(new FooModule) - val mirror = Module(new FooMirrorBlackBox) - foo.io <> mirror.io - } - } - val chirrtl = emitChirrtl(new Chisel3.Top) - chirrtl should include("foo.io.bar <= mirror.bar") - chirrtl should include("mirror.foo <= foo.io.foo") - chirrtl should include("foo.io.quz.q.bits <- mirror.quz.q.bits") - chirrtl should include("foo.io.quz.q.valid <= mirror.quz.q.valid") - } - - "A chisel3.Bundle bulk connected to a Chisel Bundle in either direction" should "work even with mismatched fields" in { - object Compat { - import Chisel._ - class FooBundle extends Bundle { - val foo = UInt(width = 8) - } - } - object Chisel3 { - import chisel3._ - class BarBundle extends Bundle { - val bar = UInt(8.W) - } - class MyModule(swap: Boolean) extends Module { - val in = IO(Input(if (swap) new Compat.FooBundle else new BarBundle)) - val out = IO(Output(if (swap) new BarBundle else new Compat.FooBundle)) - out <> DontCare - out <> in - } - } - val chirrtl0 = emitChirrtl(new Chisel3.MyModule(true)) - chirrtl0 shouldNot include("<=") - chirrtl0 should include("out <- in") - val chirrtl1 = emitChirrtl(new Chisel3.MyModule(true)) - chirrtl1 shouldNot include("<=") - chirrtl1 should include("out <- in") - } - - it should "work with missing fields in the Chisel._" in { - object Compat { - import Chisel._ - class FooBundle extends Bundle { - val foo = UInt(width = 8) - } - } - object Chisel3 { - import chisel3._ - class FooBarBundle extends Bundle { - val foo = UInt(8.W) - val bar = UInt(8.W) - } - - class MyModule(swap: Boolean) extends Module { - val in = IO(Input(if (swap) new Compat.FooBundle else new FooBarBundle)) - val out = IO(Output(if (swap) new FooBarBundle else new Compat.FooBundle)) - out <> DontCare - out <> in - } - } - val chirrtl0 = emitChirrtl(new Chisel3.MyModule(true)) - chirrtl0 shouldNot include("<=") - chirrtl0 should include("out <- in") - val chirrtl1 = emitChirrtl(new Chisel3.MyModule(true)) - chirrtl1 shouldNot include("<=") - chirrtl1 should include("out <- in") - } - - it should "work with missing fields in the chisel3._" in { - object Compat { - import Chisel._ - class FooBundle extends Bundle { - val foo = UInt(width = 8) - } - } - object Chisel3 { - import chisel3._ - class FooBarBundle extends Bundle { - val foo = UInt(8.W) - val bar = UInt(8.W) - } - - class MyModule(swap: Boolean) extends Module { - val in = IO(Input(if (swap) new Compat.FooBundle else new FooBarBundle)) - val out = IO(Output(if (swap) new FooBarBundle else new Compat.FooBundle)) - out <> DontCare - out <> in - } - } - val chirrtl0 = emitChirrtl(new Chisel3.MyModule(true)) - chirrtl0 shouldNot include("<=") - chirrtl0 should include("out <- in") - val chirrtl1 = emitChirrtl(new Chisel3.MyModule(true)) - chirrtl1 shouldNot include("<=") - chirrtl1 should include("out <- in") - } - - it should "emit FIRRTL connects if possible" in { - object Compat { - import Chisel._ - class FooBarBundle extends Bundle { - val foo = UInt(8.W) - val bar = Flipped(UInt(8.W)) - } - } - object Chisel3 { - import chisel3._ - class FooBarBundle extends Bundle { - val foo = Output(UInt(8.W)) - val bar = Input(UInt(8.W)) - } - class MyModule(swap: Boolean) extends Module { - val in = IO(Flipped((if (swap) new Compat.FooBarBundle else new FooBarBundle))) - val out = IO(if (swap) new FooBarBundle else new Compat.FooBarBundle) - out <> DontCare - out <> in - } - } - val chirrtl0 = emitChirrtl(new Chisel3.MyModule(true)) - chirrtl0 should include("out <= in") - chirrtl0 shouldNot include("out <- in") - val chirrtl1 = emitChirrtl(new Chisel3.MyModule(true)) - chirrtl1 should include("out <= in") - chirrtl1 shouldNot include("out <- in") - } -} diff --git a/src/test/scala/chiselTests/CompatibilitySpec.scala b/src/test/scala/chiselTests/CompatibilitySpec.scala deleted file mode 100644 index 5a3b43e6..00000000 --- a/src/test/scala/chiselTests/CompatibilitySpec.scala +++ /dev/null @@ -1,639 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3.stage.ChiselStage -import chisel3.testers.BasicTester - -import org.scalacheck.Gen -import org.scalatestplus.scalacheck.ScalaCheckDrivenPropertyChecks - -import scala.collection.immutable.ListMap - -// Need separate import to override compile options from Chisel._ -object CompatibilityCustomCompileOptions { - import Chisel.{defaultCompileOptions => _, _} - implicit val customCompileOptions = - chisel3.ExplicitCompileOptions.NotStrict.copy(inferModuleReset = true) - class Foo extends Module { - val io = new Bundle {} - } -} - -class CompatibiltySpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyChecks with Utils { - import Chisel._ - - behavior.of("Chisel compatibility layer") - - it should "accept direction arguments" in { - ChiselStage.elaborate(new Module { - // Choose a random direction - val directionArgument: Direction = Gen.oneOf(INPUT, OUTPUT, NODIR).sample.get - val expectedDirection = directionArgument match { - case NODIR => OUTPUT - case other => other - } - // Choose a random width - val width = Gen.choose(1, 2048).sample.get - val io = new Bundle { - val b = Bool(directionArgument) - val u = UInt(directionArgument, width) - } - io.b shouldBe a[Bool] - io.b.getWidth shouldEqual 1 - io.b.dir shouldEqual (expectedDirection) - io.u shouldBe a[UInt] - io.u.getWidth shouldEqual width - io.u.dir shouldEqual (expectedDirection) - }) - } - - it should "accept single argument U/SInt factory methods" in { - // Choose a random value - val value: Int = Gen.choose(0, Int.MaxValue).sample.get - val l = UInt(value) - l shouldBe a[UInt] - l shouldBe 'lit - l.getWidth shouldEqual BigInt(value).bitLength - l.litValue() shouldEqual value - } - - it should "map utility objects into the package object" in { - val value: Int = Gen.choose(2, 2048).sample.get - log2Up(value) shouldBe (1.max(BigInt(value - 1).bitLength)) - log2Ceil(value) shouldBe (BigInt(value - 1).bitLength) - log2Down(value) shouldBe ((1.max(BigInt(value - 1).bitLength)) - (if (value > 0 && ((value & (value - 1)) == 0)) 0 - else 1)) - log2Floor(value) shouldBe (BigInt(value - 1).bitLength - (if (value > 0 && ((value & (value - 1)) == 0)) 0 else 1)) - isPow2(BigInt(1) << value) shouldBe true - isPow2((BigInt(1) << value) - 1) shouldBe false - } - - it should "make BitPats available" in { - val value: Int = Gen.choose(1, Int.MaxValue).sample.get - val binaryString = value.toBinaryString - val maskPosition = Gen.choose(0, binaryString.length - 1).sample.get - val bs = new StringBuilder(binaryString) - bs(maskPosition) = '?' - val bitPatString = bs.toString - val bp = BitPat("b" + bitPatString) - bp shouldBe a[BitPat] - bp.getWidth shouldEqual binaryString.length - - } - - it should "successfully compile a complete module" in { - class Dummy extends Module { - // The following just checks that we can create objects with nothing more than the Chisel compatibility package. - val io = new Bundle {} - val data = UInt(width = 3) - val wire = Wire(data) - new ArbiterIO(data, 2) shouldBe a[ArbiterIO[UInt]] - Module(new LockingRRArbiter(data, 2, 2, None)) shouldBe a[LockingRRArbiter[UInt]] - Module(new RRArbiter(data, 2)) shouldBe a[RRArbiter[UInt]] - Module(new Arbiter(data, 2)) shouldBe a[Arbiter[UInt]] - new Counter(2) shouldBe a[Counter] - new ValidIO(data) shouldBe a[ValidIO[UInt]] - new DecoupledIO(data) shouldBe a[DecoupledIO[UInt]] - new QueueIO(data, 2) shouldBe a[QueueIO[UInt]] - Module(new Pipe(data, 2)) shouldBe a[Pipe[UInt]] - - FillInterleaved(2, wire) shouldBe a[UInt] - PopCount(wire) shouldBe a[UInt] - Fill(2, wire) shouldBe a[UInt] - Reverse(wire) shouldBe a[UInt] - Cat(wire, wire) shouldBe a[UInt] - Log2(wire) shouldBe a[UInt] - // 'switch' and 'is' are tested below in Risc - Counter(2) shouldBe a[Counter] - DecoupledIO(wire) shouldBe a[DecoupledIO[UInt]] - val dcd = Wire(Decoupled(data)) - dcd shouldBe a[DecoupledIO[UInt]] - Queue(dcd) shouldBe a[DecoupledIO[UInt]] - Queue(dcd, 0) shouldBe a[DecoupledIO[UInt]] - Enum(UInt(), 2) shouldBe a[List[UInt]] - ListLookup(wire, List(wire), Array((BitPat("b1"), List(wire)))) shouldBe a[List[UInt]] - Lookup(wire, wire, Seq((BitPat("b1"), wire))) shouldBe a[UInt] - Mux1H(wire, Seq(wire)) shouldBe a[UInt] - PriorityMux(Seq(Bool(false)), Seq(data)) shouldBe a[UInt] - MuxLookup(wire, wire, Seq((wire, wire))) shouldBe a[UInt] - MuxCase(wire, Seq((Bool(true), wire))) shouldBe a[UInt] - OHToUInt(wire) shouldBe a[UInt] - PriorityEncoder(wire) shouldBe a[UInt] - UIntToOH(wire) shouldBe a[UInt] - PriorityEncoderOH(wire) shouldBe a[UInt] - RegNext(wire) shouldBe a[UInt] - RegInit(wire) shouldBe a[UInt] - RegEnable(wire, Bool(true)) shouldBe a[UInt] - ShiftRegister(wire, 2) shouldBe a[UInt] - Valid(data) shouldBe a[ValidIO[UInt]] - Pipe(Wire(Valid(data)), 2) shouldBe a[ValidIO[UInt]] - } - ChiselStage.elaborate { new Dummy } - } - // Verify we can elaborate a design expressed in Chisel2 - class Chisel2CompatibleRisc extends Module { - val io = new Bundle { - val isWr = Bool(INPUT) - val wrAddr = UInt(INPUT, 8) - val wrData = Bits(INPUT, 32) - val boot = Bool(INPUT) - val valid = Bool(OUTPUT) - val out = Bits(OUTPUT, 32) - } - val file = Mem(256, Bits(width = 32)) - val code = Mem(256, Bits(width = 32)) - val pc = Reg(init = UInt(0, 8)) - - val add_op :: imm_op :: Nil = Enum(2) - - val inst = code(pc) - val op = inst(31, 24) - val rci = inst(23, 16) - val rai = inst(15, 8) - val rbi = inst(7, 0) - - val ra = Mux(rai === Bits(0), Bits(0), file(rai)) - val rb = Mux(rbi === Bits(0), Bits(0), file(rbi)) - val rc = Wire(Bits(width = 32)) - - io.valid := Bool(false) - io.out := Bits(0) - rc := Bits(0) - - when(io.isWr) { - code(io.wrAddr) := io.wrData - }.elsewhen(io.boot) { - pc := UInt(0) - }.otherwise { - switch(op) { - is(add_op) { rc := ra +% rb } - is(imm_op) { rc := (rai << 8) | rbi } - } - io.out := rc - when(rci === UInt(255)) { - io.valid := Bool(true) - }.otherwise { - file(rci) := rc - } - pc := pc +% UInt(1) - } - } - - it should "Chisel2CompatibleRisc should elaborate" in { - ChiselStage.elaborate { new Chisel2CompatibleRisc } - } - - it should "not try to assign directions to Analog" in { - ChiselStage.elaborate(new Module { - val io = new Bundle { - val port = chisel3.experimental.Analog(32.W) - } - }) - } - - class SmallBundle extends Bundle { - val f1 = UInt(width = 4) - val f2 = UInt(width = 5) - } - class BigBundle extends SmallBundle { - val f3 = UInt(width = 6) - } - - "A Module with missing bundle fields when compiled with the Chisel compatibility package" should "not throw an exception" in { - - class ConnectFieldMismatchModule extends Module { - val io = new Bundle { - val in = (new SmallBundle).asInput - val out = (new BigBundle).asOutput - } - io.out := io.in - } - ChiselStage.elaborate { new ConnectFieldMismatchModule() } - } - - "A Module in which a Reg is created with a bound type when compiled with the Chisel compatibility package" should "not throw an exception" in { - - class CreateRegFromBoundTypeModule extends Module { - val io = new Bundle { - val in = (new SmallBundle).asInput - val out = (new BigBundle).asOutput - } - val badReg = Reg(UInt(7, width = 4)) - } - ChiselStage.elaborate { new CreateRegFromBoundTypeModule() } - } - - "A Module with unwrapped IO when compiled with the Chisel compatibility package" should "not throw an exception" in { - - class RequireIOWrapModule extends Module { - val io = new Bundle { - val in = UInt(width = 32).asInput - val out = Bool().asOutput - } - io.out := io.in(1) - } - ChiselStage.elaborate { new RequireIOWrapModule() } - } - - "A Module without val io" should "throw an exception" in { - class ModuleWithoutValIO extends Module { - val foo = IO(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 { - val io = new Bundle { - val in = (UInt(width = 3)).asInput - val out = (UInt(width = 4)).asOutput - } - } - class SwappedConnectionModule extends SimpleModule { - val child = Module(new SimpleModule) - io.in := child.io.out - } - ChiselStage.elaborate { new SwappedConnectionModule() } - } - - "Vec ports" should "give default directions to children so they can be used in chisel3.util" in { - import Chisel._ - ChiselStage.elaborate(new Module { - val io = new Bundle { - val in = Vec(1, UInt(width = 8)).flip - val out = UInt(width = 8) - } - io.out := RegEnable(io.in(0), true.B) - }) - } - - "Reset" should "still walk, talk, and quack like a Bool" in { - import Chisel._ - ChiselStage.elaborate(new Module { - val io = new Bundle { - val in = Bool(INPUT) - val out = Bool(OUTPUT) - } - io.out := io.in && reset - }) - } - - "Data.dir" should "give the correct direction for io" in { - import Chisel._ - ChiselStage.elaborate(new Module { - val io = (new Bundle { - val foo = Bool(OUTPUT) - val bar = Bool().flip - }).flip - Chisel.assert(io.foo.dir == INPUT) - Chisel.assert(io.bar.dir == OUTPUT) - }) - } - - // Note: This is a regression (see https://github.com/freechipsproject/chisel3/issues/668) - it should "fail for Chisel types" in { - import Chisel._ - an[chisel3.ExpectedHardwareException] should be thrownBy extractCause[chisel3.ExpectedHardwareException] { - ChiselStage.elaborate(new Module { - val io = new Bundle {} - UInt(INPUT).dir - }) - } - } - - "Mux return value" should "be able to be used on the RHS" in { - import Chisel._ - ChiselStage.elaborate(new Module { - val gen = new Bundle { val foo = UInt(width = 8) } - val io = new Bundle { - val a = Vec(2, UInt(width = 8)).asInput - val b = Vec(2, UInt(width = 8)).asInput - val c = gen.asInput - val d = gen.asInput - val en = Bool(INPUT) - val y = Vec(2, UInt(width = 8)).asOutput - val z = gen.asOutput - } - io.y := Mux(io.en, io.a, io.b) - io.z := Mux(io.en, io.c, io.d) - }) - } - - "Chisel3 IO constructs" should "be useable in Chisel2" in { - import Chisel._ - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val in = Input(Bool()) - val foo = Output(Bool()) - val bar = Flipped(Bool()) - }) - Chisel.assert(io.in.dir == INPUT) - Chisel.assert(io.foo.dir == OUTPUT) - Chisel.assert(io.bar.dir == INPUT) - }) - } - - behavior.of("BitPat") - - it should "support old operators" in { - class Foo extends Module { - val io = IO(new Bundle {}) - - info("Deprecated method DC hasn't been removed") - val bp = BitPat.DC(4) - } - - ChiselStage.elaborate(new Foo) - } - - behavior.of("Enum") - - it should "support apply[T <: Bits](nodeType: T, n: Int): List[T]" in { - class Foo extends Module { - val io = IO(new Bundle {}) - - info("works for a UInt") - Enum(UInt(), 4) shouldBe a[List[UInt]] - - info("throw an exception for non-UInt types") - intercept[IllegalArgumentException] { - Enum(SInt(), 4) - }.getMessage should include("Only UInt supported for enums") - - info("throw an exception if the bit width is specified") - intercept[IllegalArgumentException] { - Enum(UInt(width = 8), 4) - }.getMessage should include("Bit width may no longer be specified for enums") - } - - ChiselStage.elaborate(new Foo) - } - - behavior.of("Queue") - - it should "support deprecated constructors" in { - class Foo extends Module { - val io = IO(new Bundle {}) - - info("reset: Option[Bool] constructor works") - val option = Module(new Queue(UInt(), 4, false, false, Some(Bool(true)))) - - info("reset: Bool constructor works") - val explicit = Module(new Queue(UInt(), 4, false, false, Bool(true))) - } - - ChiselStage.elaborate(new Foo) - } - - behavior.of("LFSR16") - - it should "still exist" in { - class Foo extends Module { - val io = IO(new Bundle {}) - - info("Still exists") - val lfsr = LFSR16() - - info("apply method returns a UInt") - lfsr shouldBe a[UInt] - - info("returned UInt has a width of 16") - lfsr.getWidth should be(16) - } - - ChiselStage.elaborate(new Foo) - } - - behavior.of("Mem") - - it should "support deprecated apply methods" in { - class Foo extends Module { - val io = IO(new Bundle {}) - - info("apply[T <: Data](t: T, size: BigInt): Mem[T] works") - val memBigInt = Mem(UInt(), 8: BigInt) - memBigInt shouldBe a[Mem[UInt]] - - info("apply[T <: Data](t: T, size: Int): Mem[T] works") - val memInt = Mem(SInt(), 16: Int) - memInt shouldBe a[Mem[SInt]] - } - - ChiselStage.elaborate(new Foo) - } - - behavior.of("SeqMem") - - it should "support deprecated apply methods" in { - class Foo extends Module { - val io = IO(new Bundle {}) - - info("apply[T <: Data](t: T, size: BigInt): SeqMem[T] works") - val seqMemBigInt = SeqMem(UInt(), 8: BigInt) - seqMemBigInt shouldBe a[SeqMem[UInt]] - - info("apply[T <: Data](t: T, size: Int): SeqMem[T] works") - val seqMemInt = SeqMem(UInt(), 16: Int) - seqMemInt shouldBe a[SeqMem[UInt]] - } - - ChiselStage.elaborate(new Foo) - } - - it should "support data-types of mixed directionality" in { - class Foo extends Module { - val io = IO(new Bundle {}) - val tpe = new Bundle { val foo = UInt(OUTPUT, width = 4); val bar = UInt(width = 4) } - // NOTE for some reason, the old bug this hit did not occur when `tpe` is inlined - val mem = SeqMem(tpe, 8) - mem(3.U) - - } - ChiselStage.elaborate((new Foo)) - } - - behavior.of("debug") - - it should "still exist" in { - class Foo extends Module { - val io = IO(new Bundle {}) - - val data = UInt(width = 2) - debug(data) - } - - ChiselStage.elaborate(new Foo) - } - - behavior.of("Data methods") - - behavior.of("Wire") - - it should "support legacy methods" in { - class Foo extends Module { - val io = IO(new Bundle {}) - - info("apply[T <: Data](dummy: Int = 0, init: T): T works") - val first = Wire(init = UInt("hdeadbeef")) - first shouldBe a[UInt] - - info("apply[T <: Data](t: T, init: T): T works") - val second = Wire(SInt(), SInt(-100)) - second shouldBe a[SInt] - - info("apply[T <: Data](t: T, init: DontCare.type): T works") - val third = Wire(UInt(), chisel3.DontCare) - third shouldBe a[UInt] - } - - ChiselStage.elaborate(new Foo) - } - - behavior.of("Vec") - - it should "support legacy methods" in { - class Foo extends BasicTester { - val seq = Seq(Wire(UInt(0, width = 4)), Wire(UInt(1, width = 4)), Wire(UInt(2, width = 4))) - val vec = Vec(seq) - - info("read works") - chisel3.assert(vec.read(UInt(0)) === UInt(0)) - - info("write works") - vec.write(UInt(1), UInt(3)) - chisel3.assert(vec.read(UInt(1)) === UInt(3)) - - val (_, done) = Counter(Bool(true), 4) - when(done) { stop } - } - - assertTesterPasses(new Foo) - } - - behavior.of("Bits methods") - - it should "support legacy methods" in { - class Foo extends Module { - val io = new Bundle {} - - val u = UInt(8) - val s = SInt(-4) - - info("asBits works") - s.asBits shouldBe a[Bits] - - info("toSInt works") - u.toSInt shouldBe a[SInt] - - info("toUInt works") - s.toUInt shouldBe a[UInt] - - info("toBools works") - s.toBools shouldBe a[Seq[Bool]] - } - - ChiselStage.elaborate(new Foo) - } - - it should "properly propagate custom compileOptions in Chisel.Module" in { - import CompatibilityCustomCompileOptions._ - var result: Foo = null - ChiselStage.elaborate({ result = new Foo; result }) - (result.compileOptions should be).theSameInstanceAs(customCompileOptions) - } - - it should "properly set the refs of Records" in { - class MyRecord extends Record { - val foo = Vec(1, Bool()).asInput - val bar = Vec(1, Bool()) - val elements = ListMap("in" -> foo, "out" -> bar) - def cloneType = (new MyRecord).asInstanceOf[this.type] - } - class Foo extends Module { - val io = IO(new MyRecord) - io.bar := io.foo - } - val verilog = ChiselStage.emitVerilog(new Foo) - // Check that the names are correct (and that the FIRRTL is valid) - verilog should include("assign io_out_0 = io_in_0;") - } - - it should "ignore .suggestName on field io" in { - class MyModule extends Module { - val io = new Bundle { - val foo = UInt(width = 8).asInput - val bar = UInt(width = 8).asOutput - } - io.suggestName("potato") - io.bar := io.foo - } - val verilog = ChiselStage.emitVerilog(new MyModule) - verilog should include("input [7:0] io_foo") - verilog should include("output [7:0] io_bar") - } - - it should "properly name field io" in { - class MyModule extends Module { - val io = new Bundle { - val foo = UInt(width = 8).asInput - val bar = UInt(width = 8).asOutput - } - val wire = Wire(init = io.foo) - io.bar := wire - } - val verilog = ChiselStage.emitVerilog(new MyModule) - verilog should include("input [7:0] io_foo") - verilog should include("output [7:0] io_bar") - } - - it should "properly handle hardware construction before val io is initialized" in { - class MyModule extends Module { - val foo = Wire(init = UInt(8)) - val io = new Bundle { - val in = UInt(INPUT, width = 8) - val en = Bool(INPUT) - val out = UInt(OUTPUT, width = 8) - } - io.out := foo - when(io.en) { - io.out := io.in - } - } - // Just check that this doesn't crash during elaboration. For more info see: - // https://github.com/chipsalliance/chisel3/issues/1802 - // - ChiselStage.elaborate(new MyModule) - } - - behavior.of("BlackBox") - - it should "have invalidated ports in a compatibility context" in { - class ExtModuleInvalidatedTester extends Module { - val io = IO(new Bundle { - val in = Input(UInt(8.W)) - val out = Output(UInt(8.W)) - }) - val inst = Module(new BlackBox { - val io = IO(new Bundle { - val in = Input(UInt(8.W)) - val out = Output(UInt(8.W)) - }) - }) - inst.io.in := io.in - io.out := inst.io.out - } - - val chirrtl = ChiselStage.emitChirrtl(new ExtModuleInvalidatedTester) - chirrtl should include("inst.in is invalid") - chirrtl should include("inst.out is invalid") - } -} diff --git a/src/test/scala/chiselTests/CompileOptionsTest.scala b/src/test/scala/chiselTests/CompileOptionsTest.scala deleted file mode 100644 index b39d8ee3..00000000 --- a/src/test/scala/chiselTests/CompileOptionsTest.scala +++ /dev/null @@ -1,194 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.CompileOptions._ -import chisel3.stage.ChiselStage - -class CompileOptionsSpec extends ChiselFlatSpec with Utils { - - abstract class StrictModule extends Module()(chisel3.ExplicitCompileOptions.Strict) - abstract class NotStrictModule extends Module()(chisel3.ExplicitCompileOptions.NotStrict) - - class SmallBundle extends Bundle { - val f1 = UInt(4.W) - val f2 = UInt(5.W) - } - class BigBundle extends SmallBundle { - val f3 = UInt(6.W) - } - - "A Module with missing bundle fields when compiled with implicit Strict.CompileOption " should "throw an exception" in { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - import chisel3.ExplicitCompileOptions.Strict - - class ConnectFieldMismatchModule extends Module { - val io = IO(new Bundle { - val in = Input(new SmallBundle) - val out = Output(new BigBundle) - }) - io.out := io.in - } - ChiselStage.elaborate { new ConnectFieldMismatchModule() } - } - } - - "A Module with missing bundle fields when compiled with implicit NotStrict.CompileOption " should "not throw an exception" in { - import chisel3.ExplicitCompileOptions.NotStrict - - class ConnectFieldMismatchModule extends Module { - val io = IO(new Bundle { - val in = Input(new SmallBundle) - val out = Output(new BigBundle) - }) - io.out := io.in - } - ChiselStage.elaborate { new ConnectFieldMismatchModule() } - } - - "A Module in which a Reg is created with a bound type when compiled with implicit Strict.CompileOption " should "throw an exception" in { - a[BindingException] should be thrownBy extractCause[BindingException] { - import chisel3.ExplicitCompileOptions.Strict - - class CreateRegFromBoundTypeModule extends Module { - val io = IO(new Bundle { - val in = Input(new SmallBundle) - val out = Output(new BigBundle) - }) - val badReg = Reg(7.U(4.W)) - } - ChiselStage.elaborate { new CreateRegFromBoundTypeModule() } - } - } - - "A Module in which a Reg is created with a bound type when compiled with implicit NotStrict.CompileOption " should "not throw an exception" in { - import chisel3.ExplicitCompileOptions.NotStrict - - class CreateRegFromBoundTypeModule extends Module { - val io = IO(new Bundle { - val in = Input(new SmallBundle) - val out = Output(new BigBundle) - }) - val badReg = Reg(7.U(4.W)) - } - ChiselStage.elaborate { new CreateRegFromBoundTypeModule() } - } - - "A Module with wrapped IO when compiled with implicit Strict.CompileOption " should "not throw an exception" in { - import chisel3.ExplicitCompileOptions.Strict - - class RequireIOWrapModule extends Module { - val io = IO(new Bundle { - val in = Input(UInt(32.W)) - val out = Output(Bool()) - }) - io.out := io.in(1) - } - ChiselStage.elaborate { new RequireIOWrapModule() } - } - - "A Module with unwrapped IO when compiled with implicit Strict.CompileOption " should "throw an exception" in { - a[BindingException] should be thrownBy extractCause[BindingException] { - import chisel3.ExplicitCompileOptions.Strict - - class RequireIOWrapModule extends Module { - val io = new Bundle { - val in = Input(UInt(32.W)) - val out = Output(Bool()) - } - io.out := io.in(1) - } - ChiselStage.elaborate { - new RequireIOWrapModule() - } - } - } - - "A Module connecting output as source to input as sink when compiled with implicit Strict.CompileOption " should "throw an exception" in { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - import chisel3.ExplicitCompileOptions.Strict - - class SimpleModule extends Module { - val io = IO(new Bundle { - val in = Input(UInt(3.W)) - val out = Output(UInt(4.W)) - }) - } - class SwappedConnectionModule extends SimpleModule { - val child = Module(new SimpleModule) - io.in := child.io.out - } - ChiselStage.elaborate { new SwappedConnectionModule() } - } - } - - "A Module connecting output as source to input as sink when compiled with implicit NotStrict.CompileOption " should "not throw an exception" in { - import chisel3.ExplicitCompileOptions.NotStrict - - class SimpleModule extends Module { - val io = IO(new Bundle { - val in = Input(UInt(3.W)) - val out = Output(UInt(4.W)) - }) - } - class SwappedConnectionModule extends SimpleModule { - val child = Module(new SimpleModule) - io.in := child.io.out - } - ChiselStage.elaborate { new SwappedConnectionModule() } - } - - "A Module with directionless connections when compiled with implicit Strict.CompileOption " should "throw an exception" in { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - // Verify we can suppress the inclusion of default compileOptions - import Chisel.{defaultCompileOptions => _} - import chisel3.ExplicitCompileOptions.Strict - - class SimpleModule extends Module { - val io = IO(new Bundle { - val in = Input(UInt(3.W)) - val out = Output(UInt(4.W)) - }) - val noDir = Wire(UInt(3.W)) - } - - class DirectionLessConnectionModule extends SimpleModule { - val a = 0.U(3.W) - val b = Wire(UInt(3.W)) - val child = Module(new SimpleModule) - b := child.noDir - } - ChiselStage.elaborate { new DirectionLessConnectionModule() } - } - } - - "Strict.copy()" should "be equivalent in all CompileOptions traits" in { - import chisel3.ExplicitCompileOptions.Strict - val copiedCompileOptions = Strict.copy() - assert(copiedCompileOptions.connectFieldsMustMatch == Strict.connectFieldsMustMatch) - assert(copiedCompileOptions.declaredTypeMustBeUnbound == Strict.declaredTypeMustBeUnbound) - assert(copiedCompileOptions.dontTryConnectionsSwapped == Strict.dontTryConnectionsSwapped) - assert(copiedCompileOptions.dontAssumeDirectionality == Strict.dontAssumeDirectionality) - assert(copiedCompileOptions.checkSynthesizable == Strict.checkSynthesizable) - assert(copiedCompileOptions.explicitInvalidate == Strict.explicitInvalidate) - assert(copiedCompileOptions.inferModuleReset == Strict.inferModuleReset) - assert(copiedCompileOptions.migrateInferModuleReset == Strict.migrateInferModuleReset) - assert(copiedCompileOptions.emitStrictConnects == Strict.emitStrictConnects) - } - - "NotStrict.copy()" should "be equivalent in all CompileOptions traits" in { - import chisel3.ExplicitCompileOptions.NotStrict - val copiedCompileOptions = NotStrict.copy() - assert(copiedCompileOptions.connectFieldsMustMatch == NotStrict.connectFieldsMustMatch) - assert(copiedCompileOptions.declaredTypeMustBeUnbound == NotStrict.declaredTypeMustBeUnbound) - assert(copiedCompileOptions.dontTryConnectionsSwapped == NotStrict.dontTryConnectionsSwapped) - assert(copiedCompileOptions.dontAssumeDirectionality == NotStrict.dontAssumeDirectionality) - assert(copiedCompileOptions.checkSynthesizable == NotStrict.checkSynthesizable) - assert(copiedCompileOptions.explicitInvalidate == NotStrict.explicitInvalidate) - assert(copiedCompileOptions.inferModuleReset == NotStrict.inferModuleReset) - assert(copiedCompileOptions.migrateInferModuleReset == NotStrict.migrateInferModuleReset) - assert(copiedCompileOptions.emitStrictConnects == NotStrict.emitStrictConnects) - } - -} diff --git a/src/test/scala/chiselTests/ComplexAssign.scala b/src/test/scala/chiselTests/ComplexAssign.scala deleted file mode 100644 index 99313967..00000000 --- a/src/test/scala/chiselTests/ComplexAssign.scala +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.testers.BasicTester -import chisel3.util._ -import org.scalacheck.Shrink - -class Complex[T <: Data](val re: T, val im: T) extends Bundle - -class ComplexAssign(w: Int) extends Module { - val io = IO(new Bundle { - val e = Input(Bool()) - val in = Input(new Complex(UInt(w.W), UInt(w.W))) - val out = Output(new Complex(UInt(w.W), UInt(w.W))) - }) - when(io.e) { - val tmp = Wire(new Complex(UInt(w.W), UInt(w.W))) - tmp := io.in - io.out.re := tmp.re - io.out.im := tmp.im - }.otherwise { - io.out.re := 0.U - io.out.im := 0.U - } -} - -class ComplexAssignTester(enList: List[Boolean], re: Int, im: Int) extends BasicTester { - val (cnt, wrap) = Counter(true.B, enList.size) - val dut = Module(new ComplexAssign(32)) - dut.io.in.re := re.asUInt - dut.io.in.im := im.asUInt - dut.io.e := VecInit(enList.map(_.asBool))(cnt) - val re_correct = dut.io.out.re === Mux(dut.io.e, dut.io.in.re, 0.U) - val im_correct = dut.io.out.im === Mux(dut.io.e, dut.io.in.im, 0.U) - assert(re_correct && im_correct) - when(wrap) { - stop() - } -} - -class ComplexAssignSpec extends ChiselPropSpec { - property("All complex assignments should return the correct result") { - // Disable shrinking on error. - implicit val noShrinkListVal = Shrink[List[Boolean]](_ => Stream.empty) - implicit val noShrinkInt = Shrink[Int](_ => Stream.empty) - forAll(enSequence(2), safeUInts, safeUInts) { (en: List[Boolean], re: Int, im: Int) => - assertTesterPasses { new ComplexAssignTester(en, re, im) } - } - } -} diff --git a/src/test/scala/chiselTests/ConnectSpec.scala b/src/test/scala/chiselTests/ConnectSpec.scala deleted file mode 100644 index 3a2b6d93..00000000 --- a/src/test/scala/chiselTests/ConnectSpec.scala +++ /dev/null @@ -1,196 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import org.scalatest._ - -import chisel3._ -import chisel3.experimental.{Analog, FixedPoint} -import chisel3.stage.ChiselStage -import chisel3.testers.BasicTester - -abstract class CrossCheck extends Bundle { - val in: Data - val out: Data -} - -class CrossConnects(inType: Data, outType: Data) extends Module { - val io = IO(new Bundle { - val in = Input(inType) - val out = Output(outType) - }) - io.out := io.in -} - -class PipeInternalWires extends Module { - import chisel3.util.Pipe - val io = IO(new Bundle { - val a = Input(Bool()) - val b = Input(UInt(32.W)) - }) - val pipe = Module(new Pipe(UInt(32.W), 32)) - pipe.io.enq.valid <> io.a - pipe.io.enq.bits <> io.b -} - -class CrossConnectTester(inType: Data, outType: Data) extends BasicTester { - val dut = Module(new CrossConnects(inType, outType)) - dut.io := DontCare - stop() -} - -class ConnectSpec extends ChiselPropSpec with Utils { - property("SInt := SInt should succeed") { - assertTesterPasses { new CrossConnectTester(SInt(16.W), SInt(16.W)) } - } - property("SInt := UInt should fail") { - intercept[ChiselException] { - extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(UInt(16.W), SInt(16.W)) } - } - } - } - property("SInt := FixedPoint should fail") { - intercept[ChiselException] { - extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(FixedPoint(16.W, 8.BP), UInt(16.W)) } - } - } - } - property("UInt := UInt should succeed") { - assertTesterPasses { new CrossConnectTester(UInt(16.W), UInt(16.W)) } - } - property("UInt := SInt should fail") { - intercept[ChiselException] { - extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(SInt(16.W), UInt(16.W)) } - } - } - } - property("UInt := FixedPoint should fail") { - intercept[ChiselException] { - extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(FixedPoint(16.W, 8.BP), UInt(16.W)) } - } - } - } - - property("Clock := Clock should succeed") { - assertTesterPasses { new CrossConnectTester(Clock(), Clock()) } - } - property("Clock := UInt should fail") { - intercept[ChiselException] { - extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(Clock(), UInt(16.W)) } - } - } - } - - property("FixedPoint := FixedPoint should succeed") { - assertTesterPasses { new CrossConnectTester(FixedPoint(16.W, 8.BP), FixedPoint(16.W, 8.BP)) } - } - property("FixedPoint := SInt should fail") { - intercept[ChiselException] { - extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(SInt(16.W), FixedPoint(16.W, 8.BP)) } - } - } - } - property("FixedPoint := UInt should fail") { - intercept[ChiselException] { - extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(UInt(16.W), FixedPoint(16.W, 8.BP)) } - } - } - } - - property("Analog := Analog should fail") { - intercept[ChiselException] { - extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(Analog(16.W), Analog(16.W)) } - } - } - } - property("Analog := FixedPoint should fail") { - intercept[ChiselException] { - extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(Analog(16.W), FixedPoint(16.W, 8.BP)) } - } - } - } - property("FixedPoint := Analog should fail") { - intercept[ChiselException] { - extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(FixedPoint(16.W, 8.BP), Analog(16.W)) } - } - } - } - property("Analog := UInt should fail") { - intercept[ChiselException] { - extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(Analog(16.W), UInt(16.W)) } - } - } - } - property("Analog := SInt should fail") { - intercept[ChiselException] { - extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(Analog(16.W), SInt(16.W)) } - } - } - } - property("UInt := Analog should fail") { - intercept[ChiselException] { - extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(UInt(16.W), Analog(16.W)) } - } - } - } - property("SInt := Analog should fail") { - intercept[ChiselException] { - extractCause[ChiselException] { - ChiselStage.elaborate { new CrossConnectTester(SInt(16.W), Analog(16.W)) } - } - } - } - property("Pipe internal connections should succeed") { - ChiselStage.elaborate(new PipeInternalWires) - } - - property("Connect error messages should have meaningful information") { - class InnerExample extends Module { - val myReg = RegInit(0.U(8.W)) - } - - class OuterAssignExample extends Module { - val inner = Module(new InnerExample()) - inner.myReg := false.B // ERROR - } - - val assignError = the[ChiselException] thrownBy { ChiselStage.elaborate { new OuterAssignExample } } - val expectedAssignError = """.*@: myReg in InnerExample cannot be written from module OuterAssignExample.""" - (assignError.getMessage should fullyMatch).regex(expectedAssignError) - - class OuterReadExample extends Module { - val myReg = RegInit(0.U(8.W)) - val inner = Module(new InnerExample()) - myReg := inner.myReg // ERROR - } - - val readError = the[ChiselException] thrownBy { ChiselStage.elaborate { new OuterReadExample } } - val expectedReadError = """.*@: myReg in InnerExample cannot be read from module OuterReadExample.""" - (readError.getMessage should fullyMatch).regex(expectedReadError) - - val typeMismatchError = the[ChiselException] thrownBy { - ChiselStage.elaborate { - new RawModule { - val myUInt = Wire(UInt(4.W)) - val mySInt = Wire(SInt(4.W)) - myUInt := mySInt - } - } - } - val expectedTypeMismatchError = """.*@: Sink \(UInt<4>\) and Source \(SInt<4>\) have different types.""" - (typeMismatchError.getMessage should fullyMatch).regex(expectedTypeMismatchError) - } -} diff --git a/src/test/scala/chiselTests/Counter.scala b/src/test/scala/chiselTests/Counter.scala deleted file mode 100644 index 0e2a339a..00000000 --- a/src/test/scala/chiselTests/Counter.scala +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.testers.BasicTester -import chisel3.util._ - -class CountTester(max: Int) extends BasicTester { - val cnt = Counter(max) - assert(cnt.n == max) - when(true.B) { cnt.inc() } - val expected = if (max == 0) 0.U else (max - 1).U - when(cnt.value === expected) { - stop() - } -} - -class EnableTester(seed: Int) extends BasicTester { - val ens = RegInit(seed.asUInt) - ens := ens >> 1 - - val (cntEnVal, _) = Counter(ens(0), 32) - val (_, done) = Counter(true.B, 33) - - when(done) { - assert(cntEnVal === popCount(seed).asUInt) - stop() - } -} - -class ResetTester(n: Int) extends BasicTester { - val triggerReset = WireInit(false.B) - val wasReset = RegNext(triggerReset) - val (value, _) = Counter(0 until 8, reset = triggerReset) - - triggerReset := value === (n - 1).U - - when(wasReset) { - assert(value === 0.U) - stop() - } -} - -class WrapTester(max: Int) extends BasicTester { - val (cnt, wrap) = Counter(true.B, max) - when(wrap) { - assert(cnt === (max - 1).asUInt) - stop() - } -} - -class RangeTester(r: Range) extends BasicTester { - val (cnt, wrap) = Counter(r) - val checkWrap = RegInit(false.B) - - when(checkWrap) { - assert(cnt === r.head.U) - stop() - }.elsewhen(wrap) { - assert(cnt === r.last.U) - checkWrap := true.B - } -} - -class CounterSpec extends ChiselPropSpec { - property("Counter should count up") { - for (i <- 0 until 4) { - assertTesterPasses(new CountTester(i)) - } - } - - property("Counter can be en/disabled") { - forAll(safeUInts) { (seed: Int) => whenever(seed >= 0) { assertTesterPasses { new EnableTester(seed) } } } - } - - property("Counter can be reset") { - forAll(smallPosInts) { (seed: Int) => assertTesterPasses { new ResetTester(seed) } } - } - - property("Counter should wrap") { - forAll(smallPosInts) { (max: Int) => assertTesterPasses { new WrapTester(max) } } - } - - property("Counter should handle a range") { - forAll(posRange) { (r: Range) => - assertTesterPasses { new RangeTester(r) } - } - } -} diff --git a/src/test/scala/chiselTests/CustomBundle.scala b/src/test/scala/chiselTests/CustomBundle.scala deleted file mode 100644 index ee964d2d..00000000 --- a/src/test/scala/chiselTests/CustomBundle.scala +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.experimental.{requireIsChiselType, DataMirror} -import scala.collection.immutable.ListMap - -// An example of how Record might be extended -// In this case, CustomBundle is a Record constructed from a Tuple of (String, Data) -// it is a possible implementation of a programmatic "Bundle" -// (and can by connected to MyBundle below) -final class CustomBundle(elts: (String, Data)*) extends Record { - val elements = ListMap(elts.map { - case (field, elt) => - requireIsChiselType(elt) - field -> elt - }: _*) - def apply(elt: String): Data = elements(elt) - override def cloneType: this.type = { - val cloned = elts.map { case (n, d) => n -> DataMirror.internal.chiselTypeClone(d) } - (new CustomBundle(cloned: _*)).asInstanceOf[this.type] - } -} diff --git a/src/test/scala/chiselTests/DataEqualitySpec.scala b/src/test/scala/chiselTests/DataEqualitySpec.scala deleted file mode 100644 index 8fbbaf94..00000000 --- a/src/test/scala/chiselTests/DataEqualitySpec.scala +++ /dev/null @@ -1,257 +0,0 @@ -package chiselTests - -import chisel3._ -import chisel3.experimental.VecLiterals._ -import chisel3.experimental.BundleLiterals._ -import chisel3.experimental.{Analog, ChiselRange, FixedPoint, Interval} -import chisel3.stage.ChiselStage -import chisel3.testers.BasicTester -import chisel3.util.Valid - -class EqualityModule(lhsGen: => Data, rhsGen: => Data) extends Module { - val out = IO(Output(Bool())) - - val lhs = lhsGen - val rhs = rhsGen - - out := lhs === rhs -} - -class EqualityTester(lhsGen: => Data, rhsGen: => Data) extends BasicTester { - val module = Module(new EqualityModule(lhsGen, rhsGen)) - - assert(module.out) - - stop() -} - -class AnalogBundle extends Bundle { - val analog = Analog(32.W) -} - -class AnalogExceptionModule extends Module { - class AnalogExceptionModuleIO extends Bundle { - val bundle1 = new AnalogBundle - val bundle2 = new AnalogBundle - } - - val io = IO(new AnalogExceptionModuleIO) -} - -class AnalogExceptionTester extends BasicTester { - val module = Module(new AnalogExceptionModule) - - module.io.bundle1 <> DontCare - module.io.bundle2 <> DontCare - - assert(module.io.bundle1 === module.io.bundle2) - - stop() -} - -class DataEqualitySpec extends ChiselFlatSpec with Utils { - object MyEnum extends ChiselEnum { - val sA, sB = Value - } - object MyEnumB extends ChiselEnum { - val sA, sB = Value - } - class MyBundle extends Bundle { - val a = UInt(8.W) - val b = Bool() - val c = MyEnum() - } - class LongBundle extends Bundle { - val a = UInt(48.W) - val b = SInt(32.W) - val c = FixedPoint(16.W, 4.BP) - } - class RuntimeSensitiveBundle(gen: => Bundle) extends Bundle { - val a = UInt(8.W) - val b: Bundle = gen - } - - behavior.of("UInt === UInt") - it should "pass with equal values" in { - assertTesterPasses { - new EqualityTester(0.U, 0.U) - } - } - it should "fail with differing values" in { - assertTesterFails { - new EqualityTester(0.U, 1.U) - } - } - - behavior.of("SInt === SInt") - it should "pass with equal values" in { - assertTesterPasses { - new EqualityTester(0.S, 0.S) - } - } - it should "fail with differing values" in { - assertTesterFails { - new EqualityTester(0.S, 1.S) - } - } - - behavior.of("Reset === Reset") - it should "pass with equal values" in { - assertTesterPasses { - new EqualityTester(true.B, true.B) - } - } - it should "fail with differing values" in { - assertTesterFails { - new EqualityTester(true.B, false.B) - } - } - - behavior.of("AsyncReset === AsyncReset") - it should "pass with equal values" in { - assertTesterPasses { - new EqualityTester(true.B.asAsyncReset, true.B.asAsyncReset) - } - } - it should "fail with differing values" in { - assertTesterFails { - new EqualityTester(true.B.asAsyncReset, false.B.asAsyncReset) - } - } - - behavior.of("Interval === Interval") - it should "pass with equal values" in { - assertTesterPasses { - new EqualityTester(2.I, 2.I) - } - } - it should "fail with differing values" in { - assertTesterFails { - new EqualityTester(2.I, 3.I) - } - } - - behavior.of("FixedPoint === FixedPoint") - it should "pass with equal values" in { - assertTesterPasses { - new EqualityTester(4.5.F(16.W, 4.BP), 4.5.F(16.W, 4.BP)) - } - } - it should "fail with differing values" in { - assertTesterFails { - new EqualityTester(4.5.F(16.W, 4.BP), 4.6.F(16.W, 4.BP)) - } - } - - behavior.of("ChiselEnum === ChiselEnum") - it should "pass with equal values" in { - assertTesterPasses { - new EqualityTester(MyEnum.sA, MyEnum.sA) - } - } - it should "fail with differing values" in { - assertTesterFails { - new EqualityTester(MyEnum.sA, MyEnum.sB) - } - } - - behavior.of("Vec === Vec") - it should "pass with equal sizes, equal values" in { - assertTesterPasses { - new EqualityTester( - Vec(3, UInt(8.W)).Lit(0 -> 1.U, 1 -> 2.U, 2 -> 3.U), - Vec(3, UInt(8.W)).Lit(0 -> 1.U, 1 -> 2.U, 2 -> 3.U) - ) - } - } - it should "fail with equal sizes, differing values" in { - assertTesterFails { - new EqualityTester( - Vec(3, UInt(8.W)).Lit(0 -> 1.U, 1 -> 2.U, 2 -> 3.U), - Vec(3, UInt(8.W)).Lit(0 -> 0.U, 1 -> 1.U, 2 -> 2.U) - ) - } - } - it should "throw a ChiselException with differing sizes" in { - (the[ChiselException] thrownBy extractCause[ChiselException] { - assertTesterFails { - new EqualityTester( - Vec(3, UInt(8.W)).Lit(0 -> 1.U, 1 -> 2.U, 2 -> 3.U), - Vec(4, UInt(8.W)).Lit(0 -> 1.U, 1 -> 2.U, 2 -> 3.U, 3 -> 4.U) - ) - } - }).getMessage should include("Vec sizes differ") - } - - behavior.of("Bundle === Bundle") - it should "pass with equal type, equal values" in { - assertTesterPasses { - new EqualityTester( - (new MyBundle).Lit(_.a -> 42.U, _.b -> false.B, _.c -> MyEnum.sB), - (new MyBundle).Lit(_.a -> 42.U, _.b -> false.B, _.c -> MyEnum.sB) - ) - } - } - it should "fail with equal type, differing values" in { - assertTesterFails { - new EqualityTester( - (new MyBundle).Lit(_.a -> 42.U, _.b -> false.B, _.c -> MyEnum.sB), - (new MyBundle).Lit(_.a -> 42.U, _.b -> false.B, _.c -> MyEnum.sA) - ) - } - } - it should "throw a ChiselException with differing runtime types" in { - (the[ChiselException] thrownBy extractCause[ChiselException] { - assertTesterFails { - new EqualityTester( - (new RuntimeSensitiveBundle(new MyBundle)).Lit( - _.a -> 1.U, - _.b -> (new MyBundle).Lit( - _.a -> 42.U, - _.b -> false.B, - _.c -> MyEnum.sB - ) - ), - (new RuntimeSensitiveBundle(new LongBundle)).Lit( - _.a -> 1.U, - _.b -> (new LongBundle).Lit( - _.a -> 42.U, - _.b -> 0.S, - _.c -> 4.5.F(16.W, 4.BP) - ) - ) - ) - } - }).getMessage should include("Runtime types differ") - } - - behavior.of("DontCare === DontCare") - it should "pass with two invalids" in { - assertTesterPasses { - new EqualityTester(Valid(UInt(8.W)).Lit(_.bits -> 123.U), Valid(UInt(8.W)).Lit(_.bits -> 123.U)) - } - } - it should "exhibit the same behavior as comparing two invalidated wires" in { - // Also check that two invalidated wires are equal - assertTesterPasses { - new EqualityTester(WireInit(UInt(8.W), DontCare), WireInit(UInt(8.W), DontCare)) - } - - // Compare the verilog generated from both test cases and verify that they both are equal to true - val verilog1 = ChiselStage.emitVerilog( - new EqualityModule(Valid(UInt(8.W)).Lit(_.bits -> 123.U), Valid(UInt(8.W)).Lit(_.bits -> 123.U)) - ) - val verilog2 = - ChiselStage.emitVerilog(new EqualityModule(WireInit(UInt(8.W), DontCare), WireInit(UInt(8.W), DontCare))) - - verilog1 should include("assign out = 1'h1;") - verilog2 should include("assign out = 1'h1;") - } - - behavior.of("Analog === Analog") - it should "throw a ChiselException" in { - (the[ChiselException] thrownBy extractCause[ChiselException] { - assertTesterFails { new AnalogExceptionTester } - }).getMessage should include("Equality isn't defined for Analog values") - } -} diff --git a/src/test/scala/chiselTests/DataPrint.scala b/src/test/scala/chiselTests/DataPrint.scala deleted file mode 100644 index 82fa1519..00000000 --- a/src/test/scala/chiselTests/DataPrint.scala +++ /dev/null @@ -1,116 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import org.scalatest._ - -import chisel3._ -import chisel3.experimental.FixedPoint -import chisel3.experimental.BundleLiterals._ -import chisel3.stage.ChiselStage -import org.scalatest.matchers.should.Matchers - -class DataPrintSpec extends ChiselFlatSpec with Matchers { - object EnumTest extends ChiselEnum { - val sNone, sOne, sTwo = Value - } - - class BundleTest extends Bundle { - val a = UInt(8.W) - val b = Bool() - } - - class PartialBundleTest extends Bundle { - val a = UInt(8.W) - val b = Bool() - val c = SInt(8.W) - val e = FixedPoint(5.W, 3.BP) - val f = EnumTest.Type() - } - - "Data types" should "have a meaningful string representation" in { - ChiselStage.elaborate { - new RawModule { - UInt().toString should be("UInt") - UInt(8.W).toString should be("UInt<8>") - SInt(15.W).toString should be("SInt<15>") - Bool().toString should be("Bool") - Clock().toString should be("Clock") - FixedPoint(5.W, 3.BP).toString should be("FixedPoint<5><<3>>") - Vec(3, UInt(2.W)).toString should be("UInt<2>[3]") - EnumTest.Type().toString should be("EnumTest") - (new BundleTest).toString should be("BundleTest") - new Bundle { val a = UInt(8.W) }.toString should be("AnonymousBundle") - new Bundle { val a = UInt(8.W) }.a.toString should be("UInt<8>") - } - } - } - - class BoundDataModule extends Module { // not in the test to avoid anon naming suffixes - Wire(UInt()).toString should be("BoundDataModule.?: Wire[UInt]") - Reg(SInt()).toString should be("BoundDataModule.?: Reg[SInt]") - val io = IO(Output(Bool())) // needs a name so elaboration doesn't fail - io.toString should be("BoundDataModule.io: IO[Bool]") - val m = Mem(4, UInt(2.W)) - m(2).toString should be("BoundDataModule.?: MemPort[UInt<2>]") - (2.U + 2.U).toString should be("BoundDataModule.?: OpResult[UInt<2>]") - Wire(Vec(3, UInt(2.W))).toString should be("BoundDataModule.?: Wire[UInt<2>[3]]") - - class InnerModule extends Module { - val io = IO(Output(new Bundle { - val a = UInt(4.W) - })) - } - val inner = Module(new InnerModule) - inner.clock.toString should be("InnerModule.clock: IO[Clock]") - inner.io.a.toString should be("InnerModule.io.a: IO[UInt<4>]") - - class FooTypeTest extends Bundle { - val foo = Vec(2, UInt(8.W)) - val fizz = UInt(8.W) - } - val tpe = new FooTypeTest - val fooio: FooTypeTest = IO(Input(tpe)) - fooio.foo(0).toString should be("BoundDataModule.fooio.foo[0]: IO[UInt<8>]") - - class NestedBundle extends Bundle { - val nestedFoo = UInt(8.W) - val nestedFooVec = Vec(2, UInt(8.W)) - } - class NestedType extends Bundle { - val foo = new NestedBundle - } - - val nestedTpe = new NestedType - val nestedio = IO(Input(nestedTpe)) - (nestedio.foo.nestedFoo.toString should be("BoundDataModule.nestedio.foo.nestedFoo: IO[UInt<8>]")) - (nestedio.foo.nestedFooVec(0).toString should be("BoundDataModule.nestedio.foo.nestedFooVec[0]: IO[UInt<8>]")) - } - - "Bound data types" should "have a meaningful string representation" in { - ChiselStage.elaborate { new BoundDataModule } - } - - "Literals" should "have a meaningful string representation" in { - ChiselStage.elaborate { - new RawModule { - 3.U.toString should be("UInt<2>(3)") - 3.U(5.W).toString should be("UInt<5>(3)") - -1.S.toString should be("SInt<1>(-1)") - false.B.toString should be("Bool(false)") - true.B.toString should be("Bool(true)") - 2.25.F(6.W, 2.BP).toString should be("FixedPoint<6><<2>>(2.25)") - -2.25.F(6.W, 2.BP).toString should be("FixedPoint<6><<2>>(-2.25)") - Vec(3, UInt(4.W)).toString should be("UInt<4>[3]") - EnumTest.sNone.toString should be("EnumTest(0=sNone)") - EnumTest.sTwo.toString should be("EnumTest(2=sTwo)") - EnumTest(1.U).toString should be("EnumTest(1=sOne)") - (new BundleTest).Lit(_.a -> 2.U, _.b -> false.B).toString should be("BundleTest(a=UInt<8>(2), b=Bool(false))") - (new PartialBundleTest).Lit().toString should be( - "PartialBundleTest(a=UInt<8>(DontCare), b=Bool(DontCare), c=SInt<8>(DontCare), e=FixedPoint<5><<3>>(DontCare), f=EnumTest(DontCare))" - ) - DontCare.toString should be("DontCare()") - } - } - } -} diff --git a/src/test/scala/chiselTests/Decoder.scala b/src/test/scala/chiselTests/Decoder.scala deleted file mode 100644 index 0c644b49..00000000 --- a/src/test/scala/chiselTests/Decoder.scala +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import org.scalacheck._ - -import chisel3._ -import chisel3.testers.BasicTester -import chisel3.util._ - -class Decoder(bitpats: List[String]) extends Module { - val io = IO(new Bundle { - val inst = Input(UInt(32.W)) - val matched = Output(Bool()) - }) - io.matched := VecInit(bitpats.map(BitPat(_) === io.inst)).reduce(_ || _) -} - -class DecoderTester(pairs: List[(String, String)]) extends BasicTester { - val (insts, bitpats) = pairs.unzip - val (cnt, wrap) = Counter(true.B, pairs.size) - val dut = Module(new Decoder(bitpats)) - dut.io.inst := VecInit(insts.map(_.asUInt))(cnt) - when(!dut.io.matched) { - assert(cnt === 0.U) - stop() - } - when(wrap) { - stop() - } -} - -class DecoderSpec extends ChiselPropSpec { - - // Use a single Int to make both a specific instruction and a BitPat that will match it - val bitpatPair = for (seed <- Arbitrary.arbitrary[Int]) yield { - val rnd = new scala.util.Random(seed) - val bs = seed.toBinaryString - val bp = bs.map(if (rnd.nextBoolean) _ else "?") - - // The following randomly throws in white space and underscores which are legal and ignored. - val bpp = bp.map { a => - if (rnd.nextBoolean) { - a - } else { - a + (if (rnd.nextBoolean) "_" else " ") - } - }.mkString - - ("b" + bs, "b" + bpp) - } - private def nPairs(n: Int) = Gen.containerOfN[List, (String, String)](n, bitpatPair) - - property("BitPat wildcards should be usable in decoding") { - forAll(nPairs(4)) { (pairs: List[(String, String)]) => - assertTesterPasses { new DecoderTester(pairs) } - } - } -} diff --git a/src/test/scala/chiselTests/DecoupledSpec.scala b/src/test/scala/chiselTests/DecoupledSpec.scala deleted file mode 100644 index 69d74aab..00000000 --- a/src/test/scala/chiselTests/DecoupledSpec.scala +++ /dev/null @@ -1,111 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.util.Decoupled - -class DecoupledSpec extends ChiselFlatSpec { - "Decoupled() and Decoupled.empty" should "give DecoupledIO with empty payloads" in { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val in = Flipped(Decoupled()) - val out = Decoupled.empty - }) - io.out <> io.in - assert(io.asUInt.widthOption.get === 4) - }) - } - - "Decoupled.map" should "apply a function to a wrapped Data" in { - val chirrtl = ChiselStage - .emitChirrtl(new Module { - val enq = IO(Flipped(Decoupled(UInt(8.W)))) - val deq = IO(Decoupled(UInt(8.W))) - deq <> enq.map(_ + 1.U) - }) - - // Check for data assignment - chirrtl should include("""node _deq_map_bits_T = add(enq.bits, UInt<1>("h1")""") - chirrtl should include("""node _deq_map_bits = tail(_deq_map_bits_T, 1)""") - chirrtl should include("""_deq_map.bits <= _deq_map_bits""") - chirrtl should include("""deq <= _deq_map""") - - // Check for back-pressure (ready signal is driven in the opposite direction of bits + valid) - chirrtl should include("""enq.ready <= _deq_map.ready""") - } - - "Decoupled.map" should "apply a function to a wrapped Bundle" in { - class TestBundle extends Bundle { - val foo = UInt(8.W) - val bar = UInt(8.W) - val fizz = Bool() - val buzz = Bool() - } - - // Add one to foo, subtract one from bar, set fizz to false and buzz to true - def func(t: TestBundle): TestBundle = { - val res = Wire(new TestBundle) - - res.foo := t.foo + 1.U - res.bar := t.bar - 1.U - res.fizz := false.B - res.buzz := true.B - - res - } - - val chirrtl = ChiselStage - .emitChirrtl(new Module { - val enq = IO(Flipped(Decoupled(new TestBundle))) - val deq = IO(Decoupled(new TestBundle)) - deq <> enq.map(func) - }) - - // Check for data assignment - chirrtl should include("""wire _deq_map_bits : { foo : UInt<8>, bar : UInt<8>, fizz : UInt<1>, buzz : UInt<1>}""") - - chirrtl should include("""node _deq_map_bits_res_foo_T = add(enq.bits.foo, UInt<1>("h1")""") - chirrtl should include("""node _deq_map_bits_res_foo_T_1 = tail(_deq_map_bits_res_foo_T, 1)""") - chirrtl should include("""_deq_map_bits.foo <= _deq_map_bits_res_foo_T_1""") - - chirrtl should include("""node _deq_map_bits_res_bar_T = sub(enq.bits.bar, UInt<1>("h1")""") - chirrtl should include("""node _deq_map_bits_res_bar_T_1 = tail(_deq_map_bits_res_bar_T, 1)""") - chirrtl should include("""_deq_map_bits.bar <= _deq_map_bits_res_bar_T_1""") - - chirrtl should include("""_deq_map_bits.fizz <= UInt<1>("h0")""") - chirrtl should include("""_deq_map_bits.buzz <= UInt<1>("h1")""") - - chirrtl should include("""_deq_map.bits <= _deq_map_bits""") - chirrtl should include("""deq <= _deq_map""") - - // Check for back-pressure (ready signal is driven in the opposite direction of bits + valid) - chirrtl should include("""enq.ready <= _deq_map.ready""") - } - - "Decoupled.map" should "apply a function to a wrapped Bundle and return a different typed DecoupledIO" in { - class TestBundle extends Bundle { - val foo = UInt(8.W) - val bar = UInt(8.W) - } - - val chirrtl = ChiselStage - .emitChirrtl(new Module { - val enq = IO(Flipped(Decoupled(new TestBundle))) - val deq = IO(Decoupled(UInt(8.W))) - deq <> enq.map(bundle => bundle.foo & bundle.bar) - }) - - // Check that the _map wire wraps a UInt and not a TestBundle - chirrtl should include("""wire _deq_map : { flip ready : UInt<1>, valid : UInt<1>, bits : UInt<8>}""") - - // Check for data assignment - chirrtl should include("""node _deq_map_bits = and(enq.bits.foo, enq.bits.bar)""") - chirrtl should include("""_deq_map.bits <= _deq_map_bits""") - chirrtl should include("""deq <= _deq_map""") - - // Check for back-pressure (ready signal is driven in the opposite direction of bits + valid) - chirrtl should include("""enq.ready <= _deq_map.ready""") - } -} diff --git a/src/test/scala/chiselTests/DedupSpec.scala b/src/test/scala/chiselTests/DedupSpec.scala deleted file mode 100644 index f2f2ed45..00000000 --- a/src/test/scala/chiselTests/DedupSpec.scala +++ /dev/null @@ -1,84 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.util._ - -class DedupIO extends Bundle { - val in = Flipped(Decoupled(UInt(32.W))) - val out = Decoupled(UInt(32.W)) -} - -class DedupQueues(n: Int) extends Module { - require(n > 0) - val io = IO(new DedupIO) - val queues = Seq.fill(n)(Module(new Queue(UInt(32.W), 4))) - var port = io.in - for (q <- queues) { - q.io.enq <> port - port = q.io.deq - } - io.out <> port -} - -/* This module creates a Queue in a nested function (such that it is not named via reflection). The - * default naming for instances prior to #470 caused otherwise identical instantiations of this - * module to have different instance names for the queues which prevented deduplication. - * NestedDedup instantiates this module twice to ensure it is deduplicated properly. - */ -class DedupSubModule extends Module { - val io = IO(new DedupIO) - io.out <> Queue(io.in, 4) -} - -class NestedDedup extends Module { - val io = IO(new DedupIO) - val inst0 = Module(new DedupSubModule) - val inst1 = Module(new DedupSubModule) - inst0.io.in <> io.in - inst1.io.in <> inst0.io.out - io.out <> inst1.io.out -} - -object DedupConsts { - val foo = 3.U -} - -class SharedConstantValDedup extends Module { - val io = IO(new Bundle { - val in = Input(UInt(8.W)) - val out = Output(UInt(8.W)) - }) - io.out := io.in + DedupConsts.foo -} - -class SharedConstantValDedupTop extends Module { - val io = IO(new Bundle { - val in = Input(UInt(8.W)) - val out = Output(UInt(8.W)) - }) - val inst0 = Module(new SharedConstantValDedup) - val inst1 = Module(new SharedConstantValDedup) - inst0.io.in := io.in - inst1.io.in := io.in - io.out := inst0.io.out + inst1.io.out -} - -class DedupSpec extends ChiselFlatSpec { - private val ModuleRegex = """\s*module\s+(\w+)\b.*""".r - def countModules(verilog: String): Int = - (verilog.split("\n").collect { case ModuleRegex(name) => name }).size - - "Deduplication" should "occur" in { - assert(countModules(compile { new DedupQueues(4) }) === 2) - } - - it should "properly dedup modules with deduped submodules" in { - assert(countModules(compile { new NestedDedup }) === 3) - } - - it should "dedup modules that share a literal" in { - assert(countModules(compile { new SharedConstantValDedupTop }) === 2) - } -} diff --git a/src/test/scala/chiselTests/Direction.scala b/src/test/scala/chiselTests/Direction.scala deleted file mode 100644 index ddbd99d2..00000000 --- a/src/test/scala/chiselTests/Direction.scala +++ /dev/null @@ -1,443 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import org.scalatest._ -import chisel3._ -import chisel3.experimental.OpaqueType -import chisel3.stage.ChiselStage -import org.scalatest.matchers.should.Matchers - -import scala.collection.immutable.SeqMap - -class DirectionedBundle extends Bundle { - val in = Input(UInt(32.W)) - val out = Output(UInt(32.W)) -} - -class DirectionHaver extends Module { - val io = IO(new Bundle { - val in = Input(UInt(32.W)) - val out = Output(UInt(32.W)) - val inBundle = Input(new DirectionedBundle) // should override elements - val outBundle = Output(new DirectionedBundle) // should override elements - }) -} - -class GoodDirection extends DirectionHaver { - io.out := 0.U - io.outBundle.in := 0.U - io.outBundle.out := 0.U -} - -class BadDirection extends DirectionHaver { - io.in := 0.U -} - -class BadSubDirection extends DirectionHaver { - io.inBundle.out := 0.U -} - -class TopDirectionOutput extends Module { - val io = IO(Output(new DirectionedBundle)) - io.in := 42.U - io.out := 117.U -} - -class DirectionSpec extends ChiselPropSpec with Matchers with Utils { - - //TODO: In Chisel3 these are actually FIRRTL errors. Remove from tests? - - property("Outputs should be assignable") { - ChiselStage.elaborate(new GoodDirection) - } - - property("Inputs should not be assignable") { - a[Exception] should be thrownBy extractCause[Exception] { - ChiselStage.elaborate(new BadDirection) - } - a[Exception] should be thrownBy extractCause[Exception] { - ChiselStage.elaborate(new BadSubDirection) - } - } - - property("Top-level forced outputs should be assignable") { - ChiselStage.elaborate(new TopDirectionOutput) - } - - property("Empty Vecs with directioned sample_element should not cause direction errors") { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val foo = Input(UInt(8.W)) - val x = Vec(0, Output(UInt(8.W))) - }) - }) - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val foo = Input(UInt(8.W)) - val x = Flipped(Vec(0, Output(UInt(8.W)))) - }) - }) - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val foo = Input(UInt(8.W)) - val x = Output(Vec(0, UInt(8.W))) - }) - }) - } - - property( - "Empty Vecs with no direction on the sample_element should not cause direction errors, as Chisel and chisel3 directions are merged" - ) { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val foo = Input(UInt(8.W)) - val x = Vec(0, UInt(8.W)) - }) - }) - } - - property("Empty Bundles should not cause direction errors") { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val foo = Input(UInt(8.W)) - val x = new Bundle {} - }) - }) - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val foo = Input(UInt(8.W)) - val x = Flipped(new Bundle {}) - }) - }) - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val foo = Input(UInt(8.W)) - val x = new Bundle { - val y = if (false) Some(Input(UInt(8.W))) else None - } - }) - }) - } - - property( - "Explicitly directioned but empty Bundles should not cause direction errors because Chisel and chisel3 directionality are merged" - ) { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val foo = UInt(8.W) - val x = Input(new Bundle {}) - }) - }) - } - - import chisel3.experimental.{DataMirror, Direction} - - property("Directions should be preserved through cloning and binding of Bundles") { - ChiselStage.elaborate(new Module { - class MyBundle extends Bundle { - val foo = Input(UInt(8.W)) - val bar = Output(UInt(8.W)) - } - class MyOuterBundle extends Bundle { - val fizz = new MyBundle - val buzz = Flipped(new MyBundle) - } - val a = new MyOuterBundle - val b = IO(a) - val specifiedDirs = Seq( - a.fizz.foo -> SpecifiedDirection.Input, - a.fizz.bar -> SpecifiedDirection.Output, - a.fizz -> SpecifiedDirection.Unspecified, - a.buzz.foo -> SpecifiedDirection.Input, - a.buzz.bar -> SpecifiedDirection.Output, - a.buzz -> SpecifiedDirection.Flip - ) - val actualDirs = Seq( - b.fizz.foo -> Direction.Input, - b.fizz.bar -> Direction.Output, - b.fizz -> Direction.Bidirectional(Direction.Default), - b.buzz.foo -> Direction.Output, - b.buzz.bar -> Direction.Input, - b.buzz -> Direction.Bidirectional(Direction.Flipped) - ) - for ((data, dir) <- specifiedDirs) { - DataMirror.specifiedDirectionOf(data) shouldBe (dir) - } - for ((data, dir) <- actualDirs) { - DataMirror.directionOf(data) shouldBe (dir) - } - }.asInstanceOf[Module]) // The cast works around weird reflection behavior (bug?) - } - - property("Directions should be preserved through cloning and binding of Vecs") { - ChiselStage.elaborate(new Module { - val a = Vec(1, Input(UInt(8.W))) - val b = Vec(1, a) - val c = Vec(1, Flipped(a)) - val io0 = IO(b) - val io1 = IO(c) - val specifiedDirs = Seq( - a(0) -> SpecifiedDirection.Input, - b(0)(0) -> SpecifiedDirection.Input, - a -> SpecifiedDirection.Unspecified, - b -> SpecifiedDirection.Unspecified, - c(0) -> SpecifiedDirection.Flip, - c(0)(0) -> SpecifiedDirection.Input, - c -> SpecifiedDirection.Unspecified - ) - val actualDirs = Seq( - io0(0)(0) -> Direction.Input, - io0(0) -> Direction.Input, - io0 -> Direction.Input, - io1(0)(0) -> Direction.Output, - io1(0) -> Direction.Output, - io1 -> Direction.Output - ) - for ((data, dir) <- specifiedDirs) { - DataMirror.specifiedDirectionOf(data) shouldBe (dir) - } - for ((data, dir) <- actualDirs) { - DataMirror.directionOf(data) shouldBe (dir) - } - }.asInstanceOf[Module]) // The cast works around weird reflection behavior (bug?) - } - - property("Using Vec and Flipped together should calculate directions properly") { - class MyModule extends RawModule { - class MyBundle extends Bundle { - val a = Input(Bool()) - val b = Output(Bool()) - } - - val index = IO(Input(UInt(1.W))) - - // Check all permutations of Vec and Flipped. - val regularVec = IO(Vec(2, new MyBundle)) - regularVec <> DontCare - assert(DataMirror.directionOf(regularVec.head.a) == Direction.Input) - assert(DataMirror.directionOf(regularVec.head.b) == Direction.Output) - assert(DataMirror.directionOf(regularVec(index).a) == Direction.Input) - assert(DataMirror.directionOf(regularVec(index).b) == Direction.Output) - - val vecFlipped = IO(Vec(2, Flipped(new MyBundle))) - vecFlipped <> DontCare - assert(DataMirror.directionOf(vecFlipped.head.a) == Direction.Output) - assert(DataMirror.directionOf(vecFlipped.head.b) == Direction.Input) - assert(DataMirror.directionOf(vecFlipped(index).a) == Direction.Output) - assert(DataMirror.directionOf(vecFlipped(index).b) == Direction.Input) - - val flippedVec = IO(Flipped(Vec(2, new MyBundle))) - flippedVec <> DontCare - assert(DataMirror.directionOf(flippedVec.head.a) == Direction.Output) - assert(DataMirror.directionOf(flippedVec.head.b) == Direction.Input) - assert(DataMirror.directionOf(flippedVec(index).a) == Direction.Output) - assert(DataMirror.directionOf(flippedVec(index).b) == Direction.Input) - - // Flipped(Vec(Flipped())) should be equal to non-flipped. - val flippedVecFlipped = IO(Flipped(Vec(2, Flipped(new MyBundle)))) - flippedVecFlipped <> DontCare - assert(DataMirror.directionOf(flippedVecFlipped.head.a) == Direction.Input) - assert(DataMirror.directionOf(flippedVecFlipped.head.b) == Direction.Output) - assert(DataMirror.directionOf(flippedVecFlipped(index).a) == Direction.Input) - assert(DataMirror.directionOf(flippedVecFlipped(index).b) == Direction.Output) - } - - val emitted: String = ChiselStage.emitChirrtl(new MyModule) - val firrtl: String = ChiselStage.convert(new MyModule).serialize - - // Check that emitted directions are correct. - Seq(emitted, firrtl).foreach { o => - { - // Chisel Emitter formats spacing a little differently than the - // FIRRTL Emitter :-( - val s = o.replace("{flip a", "{ flip a") - assert(s.contains("output regularVec : { flip a : UInt<1>, b : UInt<1>}[2]")) - assert(s.contains("input vecFlipped : { flip a : UInt<1>, b : UInt<1>}[2]")) - assert(s.contains("input flippedVec : { flip a : UInt<1>, b : UInt<1>}[2]")) - assert(s.contains("output flippedVecFlipped : { flip a : UInt<1>, b : UInt<1>}[2]")) - } - } - } - - property("Vec with Input/Output should calculate directions properly") { - class MyModule extends RawModule { - class MyBundle extends Bundle { - val a = Input(Bool()) - val b = Output(Bool()) - } - - val index = IO(Input(UInt(1.W))) - - val inputVec = IO(Vec(2, Input(new MyBundle))) - inputVec <> DontCare - assert(DataMirror.directionOf(inputVec.head.a) == Direction.Input) - assert(DataMirror.directionOf(inputVec.head.b) == Direction.Input) - assert(DataMirror.directionOf(inputVec(index).a) == Direction.Input) - assert(DataMirror.directionOf(inputVec(index).b) == Direction.Input) - - val vecInput = IO(Input(Vec(2, new MyBundle))) - vecInput <> DontCare - assert(DataMirror.directionOf(vecInput.head.a) == Direction.Input) - assert(DataMirror.directionOf(vecInput.head.b) == Direction.Input) - assert(DataMirror.directionOf(vecInput(index).a) == Direction.Input) - assert(DataMirror.directionOf(vecInput(index).b) == Direction.Input) - - val vecInputFlipped = IO(Input(Vec(2, Flipped(new MyBundle)))) - vecInputFlipped <> DontCare - assert(DataMirror.directionOf(vecInputFlipped.head.a) == Direction.Input) - assert(DataMirror.directionOf(vecInputFlipped.head.b) == Direction.Input) - assert(DataMirror.directionOf(vecInputFlipped(index).a) == Direction.Input) - assert(DataMirror.directionOf(vecInputFlipped(index).b) == Direction.Input) - - val outputVec = IO(Vec(2, Output(new MyBundle))) - outputVec <> DontCare - assert(DataMirror.directionOf(outputVec.head.a) == Direction.Output) - assert(DataMirror.directionOf(outputVec.head.b) == Direction.Output) - assert(DataMirror.directionOf(outputVec(index).a) == Direction.Output) - assert(DataMirror.directionOf(outputVec(index).b) == Direction.Output) - - val vecOutput = IO(Output(Vec(2, new MyBundle))) - vecOutput <> DontCare - assert(DataMirror.directionOf(vecOutput.head.a) == Direction.Output) - assert(DataMirror.directionOf(vecOutput.head.b) == Direction.Output) - assert(DataMirror.directionOf(vecOutput(index).a) == Direction.Output) - assert(DataMirror.directionOf(vecOutput(index).b) == Direction.Output) - - val vecOutputFlipped = IO(Output(Vec(2, Flipped(new MyBundle)))) - vecOutputFlipped <> DontCare - assert(DataMirror.directionOf(vecOutputFlipped.head.a) == Direction.Output) - assert(DataMirror.directionOf(vecOutputFlipped.head.b) == Direction.Output) - assert(DataMirror.directionOf(vecOutputFlipped(index).a) == Direction.Output) - assert(DataMirror.directionOf(vecOutputFlipped(index).b) == Direction.Output) - } - - val emitted: String = ChiselStage.emitChirrtl(new MyModule) - val firrtl: String = ChiselStage.convert(new MyModule).serialize - - // Check that emitted directions are correct. - Seq(emitted, firrtl).foreach { o => - { - // Chisel Emitter formats spacing a little differently than the - // FIRRTL Emitter :-( - val s = o.replace("{a", "{ a") - assert(s.contains("input inputVec : { a : UInt<1>, b : UInt<1>}[2]")) - assert(s.contains("input vecInput : { a : UInt<1>, b : UInt<1>}[2]")) - assert(s.contains("input vecInputFlipped : { a : UInt<1>, b : UInt<1>}[2]")) - assert(s.contains("output outputVec : { a : UInt<1>, b : UInt<1>}[2]")) - assert(s.contains("output vecOutput : { a : UInt<1>, b : UInt<1>}[2]")) - assert(s.contains("output vecOutputFlipped : { a : UInt<1>, b : UInt<1>}[2]")) - } - } - } - property("Can now describe a Decoupled bundle using Flipped, not Input/Output in chisel3") { - class Decoupled extends Bundle { - val bits = UInt(3.W) - val valid = Bool() - val ready = Flipped(Bool()) - } - class MyModule extends RawModule { - val incoming = IO(Flipped(new Decoupled)) - val outgoing = IO(new Decoupled) - - outgoing <> incoming - } - - val emitted: String = ChiselStage.emitChirrtl(new MyModule) - - // Check that emitted directions are correct. - assert(emitted.contains("input incoming : { bits : UInt<3>, valid : UInt<1>, flip ready : UInt<1>}")) - assert(emitted.contains("output outgoing : { bits : UInt<3>, valid : UInt<1>, flip ready : UInt<1>}")) - assert(emitted.contains("outgoing <= incoming")) - } - property("Can now mix Input/Output and Flipped within the same bundle") { - class Decoupled extends Bundle { - val bits = UInt(3.W) - val valid = Bool() - val ready = Flipped(Bool()) - } - class DecoupledAndMonitor extends Bundle { - val producer = new Decoupled() - val consumer = Flipped(new Decoupled()) - val monitor = Input(new Decoupled()) // Same as Flipped(stripFlipsIn(..)) - val driver = Output(new Decoupled()) // Same as stripFlipsIn(..) - } - class MyModule extends RawModule { - val io = IO(Flipped(new DecoupledAndMonitor())) - io.consumer <> io.producer - io.monitor.bits := io.driver.bits - io.monitor.valid := io.driver.valid - io.monitor.ready := io.driver.ready - } - - val emitted: String = ChiselStage.emitChirrtl(new MyModule) - - assert( - emitted.contains( - "input io : { producer : { bits : UInt<3>, valid : UInt<1>, flip ready : UInt<1>}, flip consumer : { bits : UInt<3>, valid : UInt<1>, flip ready : UInt<1>}, flip monitor : { bits : UInt<3>, valid : UInt<1>, ready : UInt<1>}, driver : { bits : UInt<3>, valid : UInt<1>, ready : UInt<1>}}" - ) - ) - assert(emitted.contains("io.consumer <= io.producer")) - assert(emitted.contains("io.monitor.bits <= io.driver.bits")) - assert(emitted.contains("io.monitor.valid <= io.driver.valid")) - assert(emitted.contains("io.monitor.ready <= io.driver.ready")) - } - property("Bugfix: marking Vec fields with mixed directionality as Output/Input clears inner directions") { - class Decoupled extends Bundle { - val bits = UInt(3.W) - val valid = Bool() - val ready = Flipped(Bool()) - } - class Coercing extends Bundle { - val source = Output(Vec(1, new Decoupled())) - val sink = Input(Vec(1, new Decoupled())) - } - class MyModule extends RawModule { - val io = IO(new Coercing()) - val source = IO(Output(Vec(1, new Decoupled()))) - val sink = IO(Input(Vec(1, new Decoupled()))) - } - - val emitted: String = ChiselStage.emitChirrtl(new MyModule) - - assert( - emitted.contains( - "output io : { source : { bits : UInt<3>, valid : UInt<1>, ready : UInt<1>}[1], flip sink : { bits : UInt<3>, valid : UInt<1>, ready : UInt<1>}[1]}" - ) - ) - assert( - emitted.contains( - "output source : { bits : UInt<3>, valid : UInt<1>, ready : UInt<1>}[1]" - ) - ) - assert( - emitted.contains( - "input sink : { bits : UInt<3>, valid : UInt<1>, ready : UInt<1>}[1]" - ) - ) - } - property("Bugfix: clearing all flips inside an opaque type") { - - class Decoupled extends Bundle { - val bits = UInt(3.W) - val valid = Bool() - val ready = Flipped(Bool()) - } - class MyOpaqueType extends Record with OpaqueType { - val k = new Decoupled() - val elements = SeqMap("" -> k) - override def cloneType: this.type = (new MyOpaqueType).asInstanceOf[this.type] - } - class MyModule extends RawModule { - val w = Wire(new MyOpaqueType()) - } - - val emitted: String = ChiselStage.emitChirrtl(new MyModule) - - assert( - emitted.contains( - "wire w : { bits : UInt<3>, valid : UInt<1>, flip ready : UInt<1>}" - ) - ) - } -} diff --git a/src/test/scala/chiselTests/DontTouchSpec.scala b/src/test/scala/chiselTests/DontTouchSpec.scala deleted file mode 100644 index 4b21840e..00000000 --- a/src/test/scala/chiselTests/DontTouchSpec.scala +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage - -class HasDeadCodeChild(withDontTouch: Boolean) extends Module { - val io = IO(new Bundle { - val a = Input(UInt(32.W)) - val b = Output(UInt(32.W)) - val c = Output(Vec(2, UInt(32.W))) - }) - io.b := io.a - io.c := DontCare - if (withDontTouch) { - dontTouch(io.c) - } -} - -class HasDeadCode(withDontTouch: Boolean) extends Module { - val io = IO(new Bundle { - val a = Input(UInt(32.W)) - val b = Output(UInt(32.W)) - }) - val inst = Module(new HasDeadCodeChild(withDontTouch)) - inst.io.a := io.a - io.b := inst.io.b - val dead = WireDefault(io.a + 1.U) - if (withDontTouch) { - dontTouch(dead) - } -} - -class DontTouchSpec extends ChiselFlatSpec with Utils { - val deadSignals = List( - "io_c_0", - "io_c_1", - "dead" - ) - "Dead code" should "be removed by default" in { - val verilog = compile(new HasDeadCode(false)) - for (signal <- deadSignals) { - (verilog should not).include(signal) - } - } - it should "NOT be removed if marked dontTouch" in { - val verilog = compile(new HasDeadCode(true)) - for (signal <- deadSignals) { - verilog should include(signal) - } - } - "Dont touch" should "only work on bound hardware" in { - a[chisel3.BindingException] should be thrownBy extractCause[BindingException] { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle {}) - dontTouch(new Bundle { val a = UInt(32.W) }) - }) - } - } -} diff --git a/src/test/scala/chiselTests/EnableShiftRegister.scala b/src/test/scala/chiselTests/EnableShiftRegister.scala deleted file mode 100644 index 4d407169..00000000 --- a/src/test/scala/chiselTests/EnableShiftRegister.scala +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests -import chisel3._ -import chisel3.stage.ChiselStage - -class EnableShiftRegister extends Module { - val io = IO(new Bundle { - val in = Input(UInt(4.W)) - val shift = Input(Bool()) - val out = Output(UInt(4.W)) - }) - val r0 = RegInit(0.U(4.W)) - val r1 = RegInit(0.U(4.W)) - val r2 = RegInit(0.U(4.W)) - val r3 = RegInit(0.U(4.W)) - when(io.shift) { - r0 := io.in - r1 := r0 - r2 := r1 - r3 := r2 - } - io.out := r3 -} - -/* -class EnableShiftRegisterTester(c: EnableShiftRegister) extends Tester(c) { - val reg = Array.fill(4){ 0 } - for (t <- 0 until 16) { - val in = rnd.nextInt(16) - val shift = rnd.nextInt(2) - println("SHIFT " + shift + " IN " + in) - poke(c.io.in, in) - poke(c.io.shift, shift) - step(1) - if (shift == 1) { - for (i <- 3 to 1 by -1) - reg(i) = reg(i-1) - reg(0) = in - } - expect(c.io.out, reg(3)) - } -} - */ - -class EnableShiftRegisterSpec extends ChiselPropSpec { - - property("EnableShiftRegister should elaborate") { - ChiselStage.elaborate { new EnableShiftRegister } - } - - ignore("EnableShiftRegisterTester should return the correct result") {} -} diff --git a/src/test/scala/chiselTests/EnumSpec.scala b/src/test/scala/chiselTests/EnumSpec.scala deleted file mode 100644 index 254439af..00000000 --- a/src/test/scala/chiselTests/EnumSpec.scala +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.util.Enum -import chisel3.testers.BasicTester - -class EnumSpec extends ChiselFlatSpec { - - "1-entry Enums" should "work" in { - assertTesterPasses(new BasicTester { - val onlyState :: Nil = Enum(1) - val wire = WireDefault(onlyState) - chisel3.assert(wire === onlyState) - stop() - }) - } -} diff --git a/src/test/scala/chiselTests/ExtModule.scala b/src/test/scala/chiselTests/ExtModule.scala deleted file mode 100644 index 3ab4cc32..00000000 --- a/src/test/scala/chiselTests/ExtModule.scala +++ /dev/null @@ -1,137 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.experimental._ -import chisel3.stage.ChiselStage -import chisel3.testers.{BasicTester, TesterDriver} - -// Avoid collisions with regular BlackBox tests by putting ExtModule blackboxes -// in their own scope. -package extmoduletests { - - import chisel3.experimental.ExtModule - - class BlackBoxInverter extends ExtModule { - val in = IO(Input(Bool())) - val out = IO(Output(Bool())) - } - - class BlackBoxPassthrough extends ExtModule { - val in = IO(Input(Bool())) - val out = IO(Output(Bool())) - } -} - -class ExtModuleTester extends BasicTester { - val blackBoxPos = Module(new extmoduletests.BlackBoxInverter) - val blackBoxNeg = Module(new extmoduletests.BlackBoxInverter) - - blackBoxPos.in := 1.U - blackBoxNeg.in := 0.U - - assert(blackBoxNeg.out === 1.U) - assert(blackBoxPos.out === 0.U) - stop() -} - -/** Instantiate multiple BlackBoxes with similar interfaces but different - * functionality. Used to detect failures in BlackBox naming and module - * deduplication. - */ - -class MultiExtModuleTester extends BasicTester { - val blackBoxInvPos = Module(new extmoduletests.BlackBoxInverter) - val blackBoxInvNeg = Module(new extmoduletests.BlackBoxInverter) - val blackBoxPassPos = Module(new extmoduletests.BlackBoxPassthrough) - val blackBoxPassNeg = Module(new extmoduletests.BlackBoxPassthrough) - - blackBoxInvPos.in := 1.U - blackBoxInvNeg.in := 0.U - blackBoxPassPos.in := 1.U - blackBoxPassNeg.in := 0.U - - assert(blackBoxInvNeg.out === 1.U) - assert(blackBoxInvPos.out === 0.U) - assert(blackBoxPassNeg.out === 0.U) - assert(blackBoxPassPos.out === 1.U) - stop() -} - -class ExtModuleWithSuggestName extends ExtModule { - val in = IO(Input(UInt(8.W))) - in.suggestName("foo") - val out = IO(Output(UInt(8.W))) -} - -class ExtModuleWithSuggestNameTester extends Module { - val in = IO(Input(UInt(8.W))) - val out = IO(Output(UInt(8.W))) - val inst = Module(new ExtModuleWithSuggestName) - inst.in := in - out := inst.out -} - -class SimpleIOBundle extends Bundle { - val in = Input(UInt(8.W)) - val out = Output(UInt(8.W)) -} - -class ExtModuleWithFlatIO extends ExtModule { - val badIO = FlatIO(new SimpleIOBundle) -} - -class ExtModuleWithFlatIOTester extends Module { - val io = IO(new SimpleIOBundle) - val inst = Module(new ExtModuleWithFlatIO) - io <> inst.badIO -} - -class ExtModuleInvalidatedTester extends Module { - val in = IO(Input(UInt(8.W))) - val out = IO(Output(UInt(8.W))) - val inst = Module(new ExtModule { - val in = IO(Input(UInt(8.W))) - val out = IO(Output(UInt(8.W))) - }) - inst.in := in - out := inst.out -} - -class ExtModuleSpec extends ChiselFlatSpec { - "A ExtModule inverter" should "work" in { - assertTesterPasses({ new ExtModuleTester }, Seq("/chisel3/BlackBoxTest.v"), TesterDriver.verilatorOnly) - } - "Multiple ExtModules" should "work" in { - assertTesterPasses({ new MultiExtModuleTester }, Seq("/chisel3/BlackBoxTest.v"), TesterDriver.verilatorOnly) - } - "DataMirror.modulePorts" should "work with ExtModule" in { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle {}) - val m = Module(new extmoduletests.BlackBoxPassthrough) - assert(DataMirror.modulePorts(m) == Seq("in" -> m.in, "out" -> m.out)) - }) - } - - behavior.of("ExtModule") - - it should "work with .suggestName (aka it should not require reflection for naming)" in { - val chirrtl = ChiselStage.emitChirrtl(new ExtModuleWithSuggestNameTester) - chirrtl should include("input foo : UInt<8>") - chirrtl should include("inst.foo <= in") - } - - it should "work with FlatIO" in { - val chirrtl = ChiselStage.emitChirrtl(new ExtModuleWithFlatIOTester) - chirrtl should include("io.out <= inst.out") - chirrtl should include("inst.in <= io.in") - chirrtl shouldNot include("badIO") - } - - it should "not have invalidated ports in a chisel3._ context" in { - val chirrtl = ChiselStage.emitChirrtl(new ExtModuleInvalidatedTester) - chirrtl shouldNot include("inst.in is invalid") - chirrtl shouldNot include("inst.out is invalid") - } -} diff --git a/src/test/scala/chiselTests/ExtModuleImpl.scala b/src/test/scala/chiselTests/ExtModuleImpl.scala deleted file mode 100644 index bb5c07bf..00000000 --- a/src/test/scala/chiselTests/ExtModuleImpl.scala +++ /dev/null @@ -1,159 +0,0 @@ -// See LICENSE for license details. - -package chiselTests - -import java.io.File - -import chisel3._ -import chisel3.experimental.ExtModule -import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} -import chisel3.util.{HasExtModuleInline, HasExtModulePath, HasExtModuleResource} -import firrtl.options.TargetDirAnnotation -import firrtl.stage.FirrtlCircuitAnnotation -import firrtl.transforms.BlackBoxNotFoundException -import org.scalatest.freespec.AnyFreeSpec -import org.scalatest.matchers.should.Matchers - -//scalastyle:off magic.number - -class ExtModuleAdd(n: Int) extends ExtModule with HasExtModuleInline { - val io = IO(new Bundle { - val in = Input(UInt(16.W)) - val out = Output(UInt(16.W)) - }) - - //scalastyle:off regex - setInline( - "ExtModuleAdd.v", - s""" - |module ExtModuleAdd( - | input [15:0] in, - | output [15:0] out - |); - | assign out = in + $n; - |endmodule - """.stripMargin - ) -} - -class UsesExtModuleAddViaInline extends Module { - val io = IO(new Bundle { - val in = Input(UInt(16.W)) - val out = Output(UInt(16.W)) - }) - - val blackBoxAdd = Module(new ExtModuleAdd(5)) - blackBoxAdd.io.in := io.in - io.out := blackBoxAdd.io.out -} - -class ExtModuleMinus extends ExtModule with HasExtModuleResource { - val io = IO(new Bundle { - val in1 = Input(UInt(16.W)) - val in2 = Input(UInt(16.W)) - val out = Output(UInt(16.W)) - }) - addResource("/chisel3/BlackBoxTest.v") -} - -class ExtModuleMinusPath extends ExtModule with HasExtModulePath { - val io = IO(new Bundle { - val in1 = Input(UInt(16.W)) - val in2 = Input(UInt(16.W)) - val out = Output(UInt(16.W)) - }) - addPath( - new File("src/test/resources/chisel3/BlackBoxTest.v").getCanonicalPath - ) -} - -class UsesExtModuleMinusViaResource extends Module { - val io = IO(new Bundle { - val in1 = Input(UInt(16.W)) - val in2 = Input(UInt(16.W)) - val out = Output(UInt(16.W)) - }) - - val mod0 = Module(new ExtModuleMinus) - - mod0.io.in1 := io.in1 - mod0.io.in2 := io.in2 - io.out := mod0.io.out -} - -class UsesExtModuleMinusViaPath extends Module { - val io = IO(new Bundle { - val in1 = Input(UInt(16.W)) - val in2 = Input(UInt(16.W)) - val out = Output(UInt(16.W)) - }) - - val mod0 = Module(new ExtModuleMinusPath) - - mod0.io.in1 := io.in1 - mod0.io.in2 := io.in2 - io.out := mod0.io.out -} - -class ExtModuleResourceNotFound extends HasExtModuleResource { - val io = IO(new Bundle {}) - addResource("/missing.resource") -} - -class UsesMissingExtModuleResource extends RawModule { - val foo = Module(new ExtModuleResourceNotFound) -} - -class ExtModuleImplSpec extends AnyFreeSpec with Matchers { - "ExtModule can have verilator source implementation" - { - - "Implementations can be contained in-line" in { - val targetDir = "test_run_dir/extmodule-inline" - - val annotations = Seq( - TargetDirAnnotation(targetDir), - ChiselGeneratorAnnotation(() => new UsesExtModuleAddViaInline) - ) - val newAnnotations = (new ChiselStage).transform(annotations) - - newAnnotations.exists(_.isInstanceOf[FirrtlCircuitAnnotation]) should be(true) - val verilogOutput = new File(targetDir, "ExtModuleAdd.v") - verilogOutput.exists() should be(true) - verilogOutput.delete() - } - - "Implementations can be contained in resource files" in { - val targetDir = "test_run_dir/extmodule-resource" - val annotations = Seq( - TargetDirAnnotation(targetDir), - ChiselGeneratorAnnotation(() => new UsesExtModuleMinusViaResource) - ) - val newAnnotations = (new ChiselStage).transform(annotations) - - newAnnotations.exists(_.isInstanceOf[FirrtlCircuitAnnotation]) should be(true) - val verilogOutput = new File(targetDir, "BlackBoxTest.v") - verilogOutput.exists() should be(true) - verilogOutput.delete() - } - - "Implementations can be contained in arbitrary files" in { - val targetDir = "test_run_dir/extmodule-path" - val annotations = Seq( - TargetDirAnnotation(targetDir), - ChiselGeneratorAnnotation(() => new UsesExtModuleMinusViaPath) - ) - val newAnnotations = (new ChiselStage).transform(annotations) - - newAnnotations.exists(_.isInstanceOf[FirrtlCircuitAnnotation]) should be(true) - val verilogOutput = new File(targetDir, "BlackBoxTest.v") - verilogOutput.exists() should be(true) - verilogOutput.delete() - } - - "Resource files that do not exist produce Chisel errors" in { - assertThrows[BlackBoxNotFoundException] { - ChiselStage.emitChirrtl(new UsesMissingExtModuleResource) - } - } - } -} diff --git a/src/test/scala/chiselTests/FixedPointSpec.scala b/src/test/scala/chiselTests/FixedPointSpec.scala deleted file mode 100644 index aedd195e..00000000 --- a/src/test/scala/chiselTests/FixedPointSpec.scala +++ /dev/null @@ -1,171 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.experimental.FixedPoint -import chisel3.internal.firrtl.{BinaryPoint, Width} -import chisel3.stage.ChiselStage -import chisel3.testers.BasicTester -import org.scalatest._ -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers - -class FixedPointLiteralSpec extends AnyFlatSpec with Matchers { - behavior.of("fixed point utilities") - - they should "allow conversion between doubles and the bigints needed to represent them" in { - val initialDouble = 0.125 - val bigInt = FixedPoint.toBigInt(initialDouble, 4) - val finalDouble = FixedPoint.toDouble(bigInt, 4) - - initialDouble should be(finalDouble) - } - - they should "have their literals support to double and to BigDecimal" in { - val d = -7.125 - val lit1 = d.F(3.BP) - lit1.litToDouble should be(d) - - val d2 = BigDecimal("1232123213131123.125") - val lit2 = d2.F(3.BP) - lit2.litToBigDecimal should be(d2) - - // Numbers that are too big will throw exception - intercept[ChiselException] { - lit2.litToDouble - } - } -} - -//noinspection TypeAnnotation,EmptyParenMethodAccessedAsParameterless -class FixedPointFromBitsTester extends BasicTester { - val uint = 3.U(4.W) - val sint = (-3).S - - val fp = FixedPoint.fromDouble(3.0, 4.W, 0.BP) - val fp_tpe = FixedPoint(4.W, 1.BP) - val uint_result = FixedPoint.fromDouble(1.5, 4.W, 1.BP) - val sint_result = FixedPoint.fromDouble(-1.5, 4.W, 1.BP) - val fp_result = FixedPoint.fromDouble(1.5, 4.W, 1.BP) - - val uint2fp = uint.asTypeOf(fp_tpe) - val sint2fp = sint.asTypeOf(fp_tpe) - val fp2fp = fp.asTypeOf(fp_tpe) - - val uintToFp = uint.asFixedPoint(1.BP) - val sintToFp = sint.asFixedPoint(1.BP) - val fpToFp = fp.asFixedPoint(1.BP) - - val negativefp = (-3.5).F(4.BP) - val positivefp = 3.5.F(4.BP) - - assert(-positivefp === negativefp) - assert(positivefp === -negativefp) - - assert(uint2fp === uint_result) - assert(sint2fp === sint_result) - assert(fp2fp === fp_result) - - assert(uintToFp === uint_result) - assert(sintToFp === sint_result) - assert(fpToFp === fp_result) - - assert(positivefp.abs() === positivefp) - assert(negativefp.abs() === positivefp) - assert(negativefp.abs() =/= negativefp) - - val f1bp5 = 1.5.F(1.BP) - val f6bp0 = 6.0.F(0.BP) - val f6bp2 = 6.0.F(2.BP) - - val f1bp5shiftleft2 = Wire(FixedPoint(Width(), BinaryPoint())) - val f6bp0shiftright2 = Wire(FixedPoint(Width(), BinaryPoint())) - val f6bp2shiftright2 = Wire(FixedPoint(Width(), BinaryPoint())) - - f1bp5shiftleft2 := f1bp5 << 2 - f6bp0shiftright2 := f6bp0 >> 2 - f6bp2shiftright2 := f6bp2 >> 2 - - assert(f1bp5shiftleft2 === f6bp0) - assert(f1bp5shiftleft2 === 6.0.F(8.BP)) - - // shifting does not move binary point, so in first case below one bit is lost in shift - assert(f6bp0shiftright2 === 1.0.F(0.BP)) - assert(f6bp2shiftright2 === 1.5.F(2.BP)) - - stop() -} - -class FixedPointMuxTester extends BasicTester { - val largeWidthLowPrecision = 6.0.F(4.W, 0.BP) - val smallWidthHighPrecision = 0.25.F(2.W, 2.BP) - val unknownWidthLowPrecision = 6.0.F(0.BP) - val unknownFixed = Wire(FixedPoint()) - unknownFixed := smallWidthHighPrecision - - assert(Mux(true.B, largeWidthLowPrecision, smallWidthHighPrecision) === 6.0.F(0.BP)) - assert(Mux(false.B, largeWidthLowPrecision, smallWidthHighPrecision) === 0.25.F(2.BP)) - assert(Mux(false.B, largeWidthLowPrecision, unknownFixed) === 0.25.F(2.BP)) - assert(Mux(true.B, unknownWidthLowPrecision, smallWidthHighPrecision) === 6.0.F(0.BP)) - - stop() -} - -class SBP extends Module { - val io = IO(new Bundle { - val in = Input(FixedPoint(6.W, 2.BP)) - val out = Output(FixedPoint(4.W, 0.BP)) - }) - io.out := io.in.setBinaryPoint(0) -} - -class SBPTester extends BasicTester { - val dut = Module(new SBP) - dut.io.in := 3.75.F(2.BP) - - assert(dut.io.out === 3.0.F(0.BP)) - - val test = Wire(FixedPoint(10.W, 5.BP)) - // Initialize test, avoiding a "Reference test is not fully initialized" error from firrtl. - test := 0.0.F(5.BP) - val q = test.setBinaryPoint(18) - assert(q.getWidth.U === 23.U) - - stop() -} - -class FixedPointLitExtractTester extends BasicTester { - assert(-4.75.F(2.BP)(1) === false.B) - assert(-4.75.F(2.BP)(2) === true.B) - assert(-4.75.F(2.BP)(100) === true.B) - assert(-4.75.F(2.BP)(3, 0) === "b1101".U) - assert(-4.75.F(2.BP)(9, 0) === "b1111101101".U) - - assert(-4.75.F(6.W, 2.BP)(1) === false.B) - assert(-4.75.F(6.W, 2.BP)(2) === true.B) - assert(-4.75.F(6.W, 2.BP)(100) === true.B) - assert(-4.75.F(6.W, 2.BP)(3, 0) === "b1101".U) - assert(-4.75.F(6.W, 2.BP)(9, 0) === "b1111101101".U) - stop() -} - -class FixedPointSpec extends ChiselPropSpec with Utils { - property("should allow set binary point") { - assertTesterPasses { new SBPTester } - } - property("should allow fromBits") { - assertTesterPasses { new FixedPointFromBitsTester } - } - property("should mux different widths and binary points") { - assertTesterPasses { new FixedPointMuxTester } - } - property("Negative shift amounts are invalid") { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate(new NegativeShift(FixedPoint(1.W, 0.BP))) - } - } - property("Bit extraction on literals should work for all non-negative indices") { - assertTesterPasses(new FixedPointLitExtractTester) - } -} diff --git a/src/test/scala/chiselTests/GCD.scala b/src/test/scala/chiselTests/GCD.scala deleted file mode 100644 index f03d4e61..00000000 --- a/src/test/scala/chiselTests/GCD.scala +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.testers.BasicTester - -class GCD extends Module { - val io = IO(new Bundle { - val a = Input(UInt(32.W)) - val b = Input(UInt(32.W)) - val e = Input(Bool()) - val z = Output(UInt(32.W)) - val v = Output(Bool()) - }) - val x = Reg(UInt(32.W)) - val y = Reg(UInt(32.W)) - when(x > y) { x := x -% y }.otherwise { y := y -% x } - when(io.e) { x := io.a; y := io.b } - io.z := x - io.v := y === 0.U -} - -class GCDTester(a: Int, b: Int, z: Int) extends BasicTester { - val dut = Module(new GCD) - val first = RegInit(true.B) - dut.io.a := a.U - dut.io.b := b.U - dut.io.e := first - when(first) { first := false.B } - when(!first && dut.io.v) { - assert(dut.io.z === z.U) - stop() - } -} - -class GCDSpec extends ChiselPropSpec { - - //TODO: use generators and this function to make z's - def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b) - - val gcds = Table( - ("a", "b", "z"), // First tuple defines column names - (64, 48, 16), // Subsequent tuples define the data - (12, 9, 3), - (48, 64, 16) - ) - - property("GCD should elaborate") { - ChiselStage.elaborate { new GCD } - } - - property("GCDTester should return the correct result") { - forAll(gcds) { (a: Int, b: Int, z: Int) => - assertTesterPasses { new GCDTester(a, b, z) } - } - } -} diff --git a/src/test/scala/chiselTests/Harness.scala b/src/test/scala/chiselTests/Harness.scala deleted file mode 100644 index d4330cd6..00000000 --- a/src/test/scala/chiselTests/Harness.scala +++ /dev/null @@ -1,85 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import java.io.File - -class HarnessSpec extends ChiselPropSpec { - - def makeTrivialVerilog: (File => File) = makeHarness((prefix: String) => s""" -module ${prefix}; - initial begin - $$display("$prefix!"); - $$finish; - end -endmodule -""", ".v") _ - - def makeFailingVerilog: (File => File) = makeHarness( - (prefix: String) => s""" -module $prefix; - initial begin - assert (1 == 0) else $$error("My specific, expected error message!"); - $$display("$prefix!"); - $$finish; - end -endmodule -""", - ".v" - ) _ - - def makeCppHarness: (File => File) = makeHarness( - (prefix: String) => s""" -#include "V$prefix.h" -#include "verilated.h" - -vluint64_t main_time = 0; -double sc_time_stamp () { return main_time; } - -int main(int argc, char **argv, char **env) { - Verilated::commandArgs(argc, argv); - V${prefix}* top = new V${prefix}; - while (!Verilated::gotFinish()) { top->eval(); } - delete top; - exit(0); -} - -void vl_finish(const char* filename, int linenum, const char* hier) { - Verilated::flushCall(); - exit(0); -} -""", - ".cpp" - ) _ - - /** Compiles a C++ emulator from Verilog and returns the path to the - * executable and the executable filename as a tuple. - */ - def simpleHarnessBackend(make: File => File): (File, String) = { - val target = "test" - val path = createTestDirectory(target) - val fname = new File(path, target) - - val cppHarness = makeCppHarness(fname) - - make(fname) - verilogToCpp(target, path, Seq(), cppHarness).! - cppToExe(target, path).! - (path, target) - } - - property("Test making trivial verilog harness and executing") { - val (path, target) = simpleHarnessBackend(makeTrivialVerilog) - - assert(executeExpectingSuccess(target, path)) - } - - property("Test that assertion failues in Verilog are caught") { - val (path, target) = simpleHarnessBackend(makeFailingVerilog) - - assert(!executeExpectingSuccess(target, path)) - assert(executeExpectingFailure(target, path)) - assert(executeExpectingFailure(target, path, "My specific, expected error message!")) - assert(!executeExpectingFailure(target, path, "A string that doesn't match any test output")) - } -} diff --git a/src/test/scala/chiselTests/IOCompatibility.scala b/src/test/scala/chiselTests/IOCompatibility.scala deleted file mode 100644 index 3e01a7a5..00000000 --- a/src/test/scala/chiselTests/IOCompatibility.scala +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage -import org.scalatest._ -import org.scalatest.matchers.should.Matchers - -class IOCSimpleIO extends Bundle { - val in = Input(UInt(32.W)) - val out = Output(UInt(32.W)) -} - -class IOCPlusOne extends Module { - val io = IO(new IOCSimpleIO) - io.out := io.in + 1.U -} - -class IOCModuleVec(val n: Int) extends Module { - val io = IO(new Bundle { - val ins = Vec(n, Input(UInt(32.W))) - val outs = Vec(n, Output(UInt(32.W))) - }) - val pluses = VecInit(Seq.fill(n) { Module(new IOCPlusOne).io }) - for (i <- 0 until n) { - pluses(i).in := io.ins(i) - io.outs(i) := pluses(i).out - } -} - -class IOCModuleWire extends Module { - val io = IO(new IOCSimpleIO) - val inc = Wire(chiselTypeOf(Module(new IOCPlusOne).io)) - inc.in := io.in - io.out := inc.out -} - -class IOCompatibilitySpec extends ChiselPropSpec with Matchers with Utils { - - property("IOCModuleVec should elaborate") { - ChiselStage.elaborate { new IOCModuleVec(2) } - } - - property("IOCModuleWire should elaborate") { - ChiselStage.elaborate { new IOCModuleWire } - } - - class IOUnwrapped extends Module { - val io = new IOCSimpleIO - io.out := io.in - } - - property("Unwrapped IO should generate an exception") { - a[BindingException] should be thrownBy extractCause[BindingException] { - ChiselStage.elaborate(new IOUnwrapped) - } - } -} diff --git a/src/test/scala/chiselTests/IllegalRefSpec.scala b/src/test/scala/chiselTests/IllegalRefSpec.scala deleted file mode 100644 index 219df5af..00000000 --- a/src/test/scala/chiselTests/IllegalRefSpec.scala +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage - -object IllegalRefSpec { - class IllegalRefInner extends RawModule { - val io = IO(new Bundle { - val i = Input(Bool()) - val o = Output(Bool()) - }) - val x = io.i & io.i - io.o := io.i - } - - class IllegalRefOuter(useConnect: Boolean) extends RawModule { - val io = IO(new Bundle { - val a = Input(Bool()) - val b = Input(Bool()) - val out = Output(Bool()) - }) - - val inst = Module(new IllegalRefInner) - io.out := inst.io.o - inst.io.i := io.a - val x = WireInit(io.b) - if (useConnect) { - val z = WireInit(inst.x) // oops - } else { - val z = inst.x & inst.x // oops - } - } - - class CrossWhenConnect(useConnect: Boolean) extends RawModule { - val io = IO(new Bundle { - val i = Input(Bool()) - val o = Output(Bool()) - }) - private var tmp: Option[Bool] = None - when(io.i) { - val x = io.i & io.i - tmp = Some(x) - } - if (useConnect) { - io.o := tmp.get - } else { - val z = tmp.get & tmp.get - io.o := io.i - } - } -} - -class IllegalRefSpec extends ChiselFlatSpec with Utils { - import IllegalRefSpec._ - - val variants = Map("a connect" -> true, "an op" -> false) - - variants.foreach { - case (k, v) => - s"Illegal cross-module references in ${k}" should "fail" in { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { new IllegalRefOuter(v) } - } - } - - s"Using a signal that has escaped its enclosing when scope in ${k}" should "fail" in { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { new CrossWhenConnect(v) } - } - } - } -} diff --git a/src/test/scala/chiselTests/ImplicitConversionsSpec.scala b/src/test/scala/chiselTests/ImplicitConversionsSpec.scala deleted file mode 100644 index 4bccf636..00000000 --- a/src/test/scala/chiselTests/ImplicitConversionsSpec.scala +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ - -class ImplicitConversionsSpec extends ChiselFlatSpec { - ".data on arbitrary Data objects" should "not work" in { - assertTypeError("UInt(8.W).data") - assertTypeError("8.S.data") - assertTypeError("(new Bundle {}).data") - assertTypeError("VecInit(1.U).data") - } - - ".target on arbitrary Data objects" should "not work" in { - assertTypeError("UInt(8.W).target") - assertTypeError("8.S.target") - assertTypeError("(new Bundle {}).target") - assertTypeError("VecInit(1.U).target") - } - - ".x on Strings and Numerical values" should "not work" in { - assertTypeError("3.x") - assertTypeError("3L.x") - assertTypeError("BigInt(-4).x") - assertTypeError("false.x") - assertTypeError(""""a".x""") - } - - ".bigint on Strings and Numerical values" should "not work" in { - assertTypeError("3.bigint") - assertTypeError("3L.bigint") - assertTypeError("BigInt(-4).bigint") - assertTypeError("false.bigint") - assertTypeError(""""a".bigint""") - } - - ".target on DecoupledIO" should "not work" in { - import chisel3.util._ - assertTypeError("Decoupled(UInt(8.W)).target") - } - - "X.B for X not in [0,1]" should "throw an exception, even outside hardware context" in { - a[ChiselException] should be thrownBy { - 65.B - } - } -} diff --git a/src/test/scala/chiselTests/InlineSpec.scala b/src/test/scala/chiselTests/InlineSpec.scala deleted file mode 100644 index 09a92e45..00000000 --- a/src/test/scala/chiselTests/InlineSpec.scala +++ /dev/null @@ -1,96 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} -import chisel3.util.experimental.{FlattenInstance, InlineInstance} -import firrtl.passes.InlineAnnotation -import firrtl.stage.{FirrtlCircuitAnnotation, FirrtlStage} -import firrtl.transforms.FlattenAnnotation -import firrtl.analyses.InstanceGraph -import firrtl.{ir => fir} -import org.scalatest.freespec.AnyFreeSpec -import org.scalatest.matchers.should.Matchers - -class InlineSpec extends AnyFreeSpec with ChiselRunners with Matchers { - - trait Internals { this: Module => - val io = IO(new Bundle { val a = Input(Bool()) }) - } - class Sub extends Module with Internals - trait HasSub { this: Module with Internals => - val sub = Module(new Sub) - sub.io.a := io.a - } - - class Foo extends Module with Internals with InlineInstance with HasSub - class Bar extends Module with Internals with HasSub - class Baz extends Module with Internals with HasSub - class Qux extends Module with Internals with HasSub - - def collectInstances(c: fir.Circuit, top: Option[String] = None): Seq[String] = - new InstanceGraph(c).fullHierarchy.values.flatten.toSeq - .map(v => (top.getOrElse(v.head.name) +: v.tail.map(_.name)).mkString(".")) - - val chiselStage = new ChiselStage - val firrtlStage = new FirrtlStage - - "Module Inlining" - { - class Top extends Module with Internals { - val x = Module(new Foo) - val y = Module(new Bar with InlineInstance) - val z = Module(new Bar) - Seq(x, y, z).map(_.io.a := io.a) - } - "should compile to low FIRRTL" - { - val chiselAnnotations = - chiselStage - .execute( - Array("--no-run-firrtl", "--target-dir", "test_run_dir"), - Seq(ChiselGeneratorAnnotation(() => new Top)) - ) - - (chiselAnnotations.collect { case a: InlineAnnotation => a } should have).length(2) - - val instanceNames = - firrtlStage - .execute(Array("-X", "low"), chiselAnnotations) - .collectFirst { - case FirrtlCircuitAnnotation(circuit) => circuit - } - .map(collectInstances(_, Some("Top"))) - .getOrElse(fail) - - instanceNames should contain theSameElementsAs Set("Top", "Top.x_sub", "Top.y_sub", "Top.z", "Top.z.sub") - } - } - - "Module Flattening" - { - class Top extends Module with Internals { - val x = Module(new Qux with FlattenInstance) - x.io.a := io.a - } - "should compile to low FIRRTL" - { - val chiselAnnotations = - chiselStage - .execute( - Array("--no-run-firrtl", "--target-dir", "test_run_dir"), - Seq(ChiselGeneratorAnnotation(() => new Top)) - ) - - (chiselAnnotations.collect { case a: FlattenAnnotation => a } should have).length(1) - - val instanceNames = - firrtlStage - .execute(Array("-X", "low"), chiselAnnotations) - .collectFirst { - case FirrtlCircuitAnnotation(circuit) => circuit - } - .map(collectInstances(_, Some("Top"))) - .getOrElse(fail) - - instanceNames should contain theSameElementsAs Set("Top", "Top.x") - } - } -} diff --git a/src/test/scala/chiselTests/InstanceNameSpec.scala b/src/test/scala/chiselTests/InstanceNameSpec.scala deleted file mode 100644 index cc5980f4..00000000 --- a/src/test/scala/chiselTests/InstanceNameSpec.scala +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.util.Queue - -class InstanceNameModule extends Module { - val io = IO(new Bundle { - val foo = Input(UInt(32.W)) - val bar = Output(UInt(32.W)) - }) - val x = 3.U - val y = UInt(8.W) - val z = new Bundle { - val foo = UInt(8.W) - } - - val q = Module(new Queue(UInt(32.W), 4)) - - io.bar := io.foo + x -} - -class InstanceNameSpec extends ChiselFlatSpec with Utils { - behavior.of("instanceName") - val moduleName = "InstanceNameModule" - var m: InstanceNameModule = _ - ChiselStage.elaborate { m = new InstanceNameModule; m } - - val deprecationMsg = "Accessing the .instanceName or .toTarget of non-hardware Data is deprecated" - - it should "work with module IO" in { - val io = m.io.pathName - assert(io == moduleName + ".io") - } - - it should "work for literals" in { - val x = m.x.pathName - assert(x == moduleName + ".UInt<2>(\"h03\")") - } - - it should "work with non-hardware values (but be deprecated)" in { - val (ylog, y) = grabLog(m.y.pathName) - val (zlog, z) = grabLog(m.z.pathName) - ylog should include(deprecationMsg) - assert(y == moduleName + ".y") - zlog should include(deprecationMsg) - assert(z == moduleName + ".z") - } - - it should "work with non-hardware bundle elements (but be deprecated)" in { - val (log, foo) = grabLog(m.z.foo.pathName) - log should include(deprecationMsg) - assert(foo == moduleName + ".z.foo") - } - - it should "work with modules" in { - val q = m.q.pathName - assert(q == moduleName + ".q") - } -} diff --git a/src/test/scala/chiselTests/IntegerMathSpec.scala b/src/test/scala/chiselTests/IntegerMathSpec.scala deleted file mode 100644 index 166e47bd..00000000 --- a/src/test/scala/chiselTests/IntegerMathSpec.scala +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.testers.BasicTester - -class IntegerMathTester extends BasicTester { - - //TODO: Add more operators - - /* absolute values tests */ - - val uint = 3.U(4.W) - val sint = (-3).S - val sintpos = 3.S - val wrongSIntPos = 4.S - - assert(uint.abs() === uint) - assert(sint.abs() === sintpos) - assert(sintpos.abs() === sintpos) - - assert(sint.abs() =/= wrongSIntPos) - - stop() -} - -class IntegerMathSpec extends ChiselPropSpec { - property("All integer ops should return the correct result") { - assertTesterPasses { new IntegerMathTester } - } -} diff --git a/src/test/scala/chiselTests/IntervalRangeSpec.scala b/src/test/scala/chiselTests/IntervalRangeSpec.scala deleted file mode 100644 index 777e08d6..00000000 --- a/src/test/scala/chiselTests/IntervalRangeSpec.scala +++ /dev/null @@ -1,237 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.experimental._ -import _root_.firrtl.{ir => firrtlir} -import chisel3.internal.firrtl.{BinaryPoint, IntervalRange, KnownBinaryPoint, UnknownBinaryPoint} -import org.scalatest.freespec.AnyFreeSpec -import org.scalatest.matchers.should.Matchers - -class IntervalRangeSpec extends AnyFreeSpec with Matchers { - - "IntervalRanges" - { - def C(b: BigDecimal): firrtlir.Bound = firrtlir.Closed(b) - - def O(b: BigDecimal): firrtlir.Bound = firrtlir.Open(b) - - def U(): firrtlir.Bound = firrtlir.UnknownBound - - def UBP(): BinaryPoint = UnknownBinaryPoint - - def checkRange(r: IntervalRange, l: firrtlir.Bound, u: firrtlir.Bound, b: BinaryPoint): Unit = { - r.lowerBound should be(l) - r.upperBound should be(u) - r.binaryPoint should be(b) - } - - def checkBinaryPoint(r: IntervalRange, b: BinaryPoint): Unit = { - r.binaryPoint should be(b) - } - - "IntervalRange describes the range of values of the Interval Type" - { - "Factory methods can create IntervalRanges" - { - "ranges can start or end open or closed, default binary point is none" in { - checkRange(range"[0,10]", C(0), C(10), 0.BP) - checkRange(range"[-1,10)", C(-1), O(10), 0.BP) - checkRange(range"(11,12]", O(11), C(12), 0.BP) - checkRange(range"(-21,-10)", O(-21), O(-10), 0.BP) - } - - "ranges can have unknown bounds" in { - checkRange(range"[?,10]", U(), C(10), 0.BP) - checkRange(range"(?,10]", U(), C(10), 0.BP) - checkRange(range"[-1,?]", C(-1), U(), 0.BP) - checkRange(range"[-1,?)", C(-1), U(), 0.BP) - checkRange(range"[?,?]", U(), U(), 0.BP) - checkRange(range"[?,?].?", U(), U(), UBP()) - } - - "binary points can be specified" in { - checkBinaryPoint(range"[?,10].0", 0.BP) - checkBinaryPoint(range"[?,10].2", 2.BP) - checkBinaryPoint(range"[?,10].?", UBP()) - } - "malformed ranges will throw ChiselException or are compile time errors" in { - // must be a cleverer way to show this - intercept[ChiselException] { - range"[19,5]" - } - assertDoesNotCompile(""" range"?,10] """) - assertDoesNotCompile(""" range"?,? """) - } - } - } - - "Ranges can be specified for UInt, SInt, and FixedPoint" - { - "invalid range specifiers should fail at compile time" in { - assertDoesNotCompile(""" range"" """) - assertDoesNotCompile(""" range"[]" """) - assertDoesNotCompile(""" range"0" """) - assertDoesNotCompile(""" range"[0]" """) - assertDoesNotCompile(""" range"[0, 1" """) - assertDoesNotCompile(""" range"0, 1]" """) - assertDoesNotCompile(""" range"[0, 1, 2]" """) - assertDoesNotCompile(""" range"[a]" """) - assertDoesNotCompile(""" range"[a, b]" """) - assertCompiles(""" range"[0, 1]" """) // syntax sanity check - } - - "range macros should allow open and closed bounds" in { - range"[-1, 1)" should be(range"[-1,1).0") - range"[-1, 1)" should be(IntervalRange(C(-1), O(1), 0.BP)) - range"[-1, 1]" should be(IntervalRange(C(-1), C(1), 0.BP)) - range"(-1, 1]" should be(IntervalRange(O(-1), C(1), 0.BP)) - range"(-1, 1)" should be(IntervalRange(O(-1), O(1), 0.BP)) - } - - "range specifiers should be whitespace tolerant" in { - range"[-1,1)" should be(IntervalRange(C(-1), O(1), 0.BP)) - range" [-1,1) " should be(IntervalRange(C(-1), O(1), 0.BP)) - range" [ -1 , 1 ) " should be(IntervalRange(C(-1), O(1), 0.BP)) - range" [ -1 , 1 ) " should be(IntervalRange(C(-1), O(1), 0.BP)) - } - - "range macros should work with interpolated variables" in { - val a = 10 - val b = -3 - - range"[$b, $a)" should be(IntervalRange(C(b), O(a), 0.BP)) - range"[${a + b}, $a)" should be(IntervalRange(C(a + b), O(a), 0.BP)) - range"[${-3 - 7}, ${-3 + a})" should be(IntervalRange(C(-10), O(-3 + a), 0.BP)) - - def number(n: Int): Int = n - - range"[${number(1)}, ${number(3)})" should be(IntervalRange(C(1), O(3), 0.BP)) - } - - "UInt should get the correct width from a range" in { - UInt(range"[0, 8)").getWidth should be(3) - UInt(range"[0, 8]").getWidth should be(4) - UInt(range"[0, 0]").getWidth should be(1) - } - - "SInt should get the correct width from a range" in { - SInt(range"[0, 8)").getWidth should be(4) - SInt(range"[0, 8]").getWidth should be(5) - SInt(range"[-4, 4)").getWidth should be(3) - SInt(range"[0, 0]").getWidth should be(1) - } - - "UInt should check that the range is valid" in { - an[ChiselException] should be thrownBy { - UInt(range"[1, 0]") - } - an[ChiselException] should be thrownBy { - UInt(range"[-1, 1]") - } - an[ChiselException] should be thrownBy { - UInt(range"(0,0]") - } - an[ChiselException] should be thrownBy { - UInt(range"[0,0)") - } - an[ChiselException] should be thrownBy { - UInt(range"(0,0)") - } - an[ChiselException] should be thrownBy { - UInt(range"(0,1)") - } - } - - "SInt should check that the range is valid" in { - an[ChiselException] should be thrownBy { - SInt(range"[1, 0]") - } - an[ChiselException] should be thrownBy { - SInt(range"(0,0]") - } - an[ChiselException] should be thrownBy { - SInt(range"[0,0)") - } - an[ChiselException] should be thrownBy { - SInt(range"(0,0)") - } - an[ChiselException] should be thrownBy { - SInt(range"(0,1)") - } - } - } - - "shift operations should work on ranges" - { - "<<, shiftLeft affects the bounds but not the binary point" in { - checkRange(range"[0,7].1", C(0), C(7), 1.BP) - checkRange(range"[0,7].1" << 1, C(0), C(14), 1.BP) - - checkRange(range"[2,7].2", C(2), C(7), 2.BP) - checkRange(range"[2,7].2" << 1, C(4), C(14), 2.BP) - } - - ">>, shiftRight affects the bounds but not the binary point" in { - checkRange(range"[0,7].0", C(0), C(7), 0.BP) - checkRange(range"[0,7].0" >> 1, C(0), C(3), 0.BP) - - checkRange(range"[0,7].1", C(0), C(7), 1.BP) - checkRange(range"[0,7].1" >> 1, C(0), C(3.5), 1.BP) - - checkRange(range"[2,7].2", C(2), C(7), 2.BP) - checkRange(range"[2,7].2" >> 1, C(1), C(3.5), 2.BP) - - checkRange(range"[2,7].2", C(2), C(7), 2.BP) - checkRange(range"[2,7].2" >> 2, C(0.5), C(1.75), 2.BP) - - // the 7(b111) >> 3 => 0.875(b0.111) but since - // binary point is two, lopping must occur so 0.875 becomes 0.75 - checkRange(range"[-8,7].2", C(-8), C(7), 2.BP) - checkRange(range"[-8,7].2" >> 3, C(-1), C(0.75), 2.BP) - - checkRange(range"(0,7).0", O(0), O(7), 0.BP) - checkRange(range"(0,7).0" >> 1, O(0), O(3), 0.BP) - - checkRange(range"(0,7).1", O(0), O(7), 1.BP) - checkRange(range"(0,7).1" >> 1, O(0), O(3.5), 1.BP) - - checkRange(range"(2,7).2", O(2), O(7), 2.BP) - checkRange(range"(2,7).2" >> 1, O(1), O(3.5), 2.BP) - - checkRange(range"(2,7).2", O(2), O(7), 2.BP) - checkRange(range"(2,7).2" >> 2, O(0.5), O(1.75), 2.BP) - - // the 7(b111) >> 3 => 0.875(b0.111) but since - // binary point is two, lopping must occur so 0.875 becomes 0.75 - checkRange(range"(-8,7).2", O(-8), O(7), 2.BP) - checkRange(range"(-8,7).2" >> 3, O(-1), O(0.75), 2.BP) - } - - "set precision can change the bounds due to precision loss, direction of change is always to lower value" in { - intercept[ChiselException] { - checkRange(range"[-7.875,7.875].3".setPrecision(UnknownBinaryPoint), C(-7.875), C(7.875), 5.BP) - } - - checkRange(range"[-7.875,7.875].3", C(-7.875), C(7.875), 3.BP) - checkRange(range"[1.25,2].2".setPrecision(1.BP), C(1.0), C(2), 1.BP) - checkRange(range"[-7.875,7.875].3".setPrecision(5.BP), C(-7.875), C(7.875), 5.BP) - checkRange(range"[-7.875,7.875].3".setPrecision(1.BP), C(-8.0), C(7.5), 1.BP) - } - } - - "get possible values should return all values from high to low" in { - var range = range"[0,4]" - range.getLowestPossibleValue should be(Some(0)) - range.getHighestPossibleValue should be(Some(4)) - range.getPossibleValues should be(Seq(0, 1, 2, 3, 4)) - - range = range"(0,4)" - range.getLowestPossibleValue should be(Some(1)) - range.getHighestPossibleValue should be(Some(3)) - range.getPossibleValues should be(Seq(1, 2, 3)) - - range = range"(-1,4).1" - range.getLowestPossibleValue should be(Some(-0.5)) - range.getHighestPossibleValue should be(Some(3.5)) - range.getPossibleValues should be(Seq(-0.5, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5)) - } - } - -} diff --git a/src/test/scala/chiselTests/IntervalSpec.scala b/src/test/scala/chiselTests/IntervalSpec.scala deleted file mode 100644 index a2d36579..00000000 --- a/src/test/scala/chiselTests/IntervalSpec.scala +++ /dev/null @@ -1,962 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import scala.language.reflectiveCalls -import _root_.firrtl.ir.{Closed, Open} -import chisel3._ -import chisel3.internal.firrtl.{IntervalRange, KnownBinaryPoint} -import chisel3.internal.sourceinfo.{SourceInfo, UnlocatableSourceInfo} -import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} -import chisel3.testers.BasicTester -import cookbook.CookbookTester -import firrtl.options.TargetDirAnnotation -import firrtl.passes.CheckTypes.InvalidConnect -import firrtl.passes.CheckWidths.{DisjointSqueeze, InvalidRange} -import firrtl.passes.{PassExceptions, WrapWithRemainder} -import firrtl.stage.{CompilerAnnotation, FirrtlCircuitAnnotation} -import firrtl.{ - HighFirrtlCompiler, - LowFirrtlCompiler, - MiddleFirrtlCompiler, - MinimumVerilogCompiler, - NoneCompiler, - SystemVerilogCompiler, - VerilogCompiler -} -import org.scalatest.freespec.AnyFreeSpec -import org.scalatest.matchers.should.Matchers - -//noinspection TypeAnnotation - -object IntervalTestHelper { - - /** Compiles a Chisel Module to Verilog - * NOTE: This uses the "test_run_dir" as the default directory for generated code. - * @param compilerName the generator for the module - * @param gen the generator for the module - * @return the Verilog code as a string. - */ - def makeFirrtl[T <: RawModule](compilerName: String)(gen: () => T): String = { - (new ChiselStage) - .execute( - Array("--compiler", compilerName, "--target-dir", "test_run_dir/IntervalSpec"), - Seq(ChiselGeneratorAnnotation(gen)) - ) - .collectFirst { case FirrtlCircuitAnnotation(source) => source } match { - case Some(circuit) => circuit.serialize - case _ => - throw new Exception( - s"makeFirrtl($compilerName) failed to generate firrtl circuit" - ) - } - - } -} - -import chiselTests.IntervalTestHelper.makeFirrtl -import chisel3.experimental._ -import chisel3.experimental.Interval - -class IntervalTest1 extends Module { - val io = IO(new Bundle { - val in1 = Input(Interval(range"[0,4]")) - val in2 = Input(Interval(range"[0,4].3")) - val out = Output(Interval(range"[0,8].3")) - }) - - io.out := io.in1 + io.in2 -} - -class IntervalTester extends CookbookTester(10) { - - val dut = Module(new IntervalTest1) - - dut.io.in1 := BigInt(4).I - dut.io.in2 := 4.I - assert(dut.io.out === 8.I) - - val i = Interval(range"[0,10)") - stop() -} - -class IntervalTest2 extends Module { - val io = IO(new Bundle { - val p = Input(Bool()) - val in1 = Input(Interval(range"[0,4]")) - val in2 = Input(Interval(range"[0,6]")) - val out = Output(Interval()) - }) - - io.out := Mux(io.p, io.in1, io.in2) -} - -class IntervalTester2 extends CookbookTester(10) { - - val dut = Module(new IntervalTest2) - - dut.io.p := 1.U - dut.io.in1 := 4.I - dut.io.in2 := 5.I - assert(dut.io.out === 4.I) - - stop() -} - -class IntervalAddTester extends BasicTester { - - val in1 = Wire(Interval(range"[0,4]")) - val in2 = Wire(Interval(range"[0,4]")) - - in1 := 2.I - in2 := 2.I - - 5.U - - val result = in1 +& in2 - - assert(result === 4.I) - - stop() - -} - -class IntervalSetBinaryPointTester extends BasicTester { - implicit val sourceinfo: SourceInfo = UnlocatableSourceInfo - val in1 = Wire(Interval(range"[0,4].4")) - val in2 = in1.setPrecision(2) - - assert(in2.binaryPoint == KnownBinaryPoint(2)) - - in1 := 2.I - - val shiftedLeft = in1.increasePrecision(2) - - assert( - shiftedLeft.binaryPoint == KnownBinaryPoint(6), - s"Error: increasePrecision result ${shiftedLeft.range} expected bt = 2" - ) - - val shiftedRight = in1.decreasePrecision(2) - - assert( - shiftedRight.binaryPoint == KnownBinaryPoint(2), - s"Error: increasePrecision result ${shiftedRight.range} expected bt = 2" - ) - - stop() -} - -class MoreIntervalShiftTester extends BasicTester { - implicit val sourceinfo: SourceInfo = UnlocatableSourceInfo - - val in1 = Wire(Interval(range"[0,4].4")) - val in2 = in1.setPrecision(2) - - assert(in2.binaryPoint == KnownBinaryPoint(2)) - - val toShiftLeft = Wire(Interval(range"[0,4].4")) - val shiftedLeft = in1.increasePrecision(2) - - assert( - shiftedLeft.binaryPoint == KnownBinaryPoint(2), - s"Error: decreasePrecision result ${shiftedLeft.range} expected bt = 2" - ) - - val toShiftRight = Wire(Interval(range"[0,4].4")) - val shiftedRight = in1.decreasePrecision(2) - - assert( - shiftedRight.binaryPoint == KnownBinaryPoint(6), - s"Error: decreasePrecision result ${shiftedRight.range} expected bt = 2" - ) - - stop() -} - -/** - * This is a reality check not a test. Makes it easier to figure out - * what is going on in other places - * @param range a range for inputs - * @param targetRange a range for outputs - * @param startNum start here - * @param endNum end here - * @param incNum increment by this - */ -class ClipSqueezeWrapDemo( - range: IntervalRange, - targetRange: IntervalRange, - startNum: Double, - endNum: Double, - incNum: Double) - extends BasicTester { - - val binaryPointAsInt = range.binaryPoint.asInstanceOf[KnownBinaryPoint].value -// val startValue = Interval.fromDouble(startNum, binaryPoint = binaryPointAsInt) -// val increment = Interval.fromDouble(incNum, binaryPoint = binaryPointAsInt) -// val endValue = Interval.fromDouble(endNum, binaryPoint = binaryPointAsInt) - val startValue = startNum.I(range.binaryPoint) - val increment = incNum.I(range.binaryPoint) - val endValue = endNum.I(range.binaryPoint) - - val counter = RegInit(Interval(range), startValue) - - counter := (counter + increment).squeeze(counter) - when(counter > endValue) { - stop() - } - - val clipped = counter.clip(0.U.asInterval(targetRange)) - val squeezed = counter.squeeze(0.U.asInterval(targetRange)) - val wrapped = counter.wrap(0.U.asInterval(targetRange)) - - when(counter === startValue) { - printf(cf"Target range is $range\n") - printf("value clip squeeze wrap\n") - } - - printf( - " %d %d %d %d\n", - counter.asSInt(), - clipped.asSInt(), - squeezed.asSInt(), - wrapped.asSInt() - ) -} - -class SqueezeFunctionalityTester(range: IntervalRange, startNum: BigDecimal, endNum: BigDecimal, increment: BigDecimal) - extends BasicTester { - - val counter = RegInit(0.U(10.W)) - counter := counter + 1.U - when(counter > 10.U) { - stop() - } - - val squeezeInterval = Wire(Interval(range)) - squeezeInterval := 0.I - - val squeezeTemplate = Wire(Interval(range)) - - val ss = WireInit(Interval(range), (-10).S.asInterval(range)) - - val toSqueeze = counter.asInterval(range) - ss - - squeezeTemplate := toSqueeze.squeeze(squeezeInterval) - - printf( - cf"SqueezeTest $counter%d ${toSqueeze.asSInt()}%d.squeeze($range) => ${squeezeTemplate.asSInt()}%d\n" - ) -} - -/** - * Demonstrate a simple counter register with an Interval type - */ -class IntervalRegisterTester extends BasicTester { - - val range = range"[-2,5]" - val counter = RegInit(Interval(range), (-1).I) - counter := (counter + 1.I) - .squeeze(counter) // this works with other types, why not Interval - when(counter > 4.I) { - stop() - } -} - -//noinspection ScalaStyle -class IntervalWrapTester extends BasicTester { - - val t1 = Wire(Interval(range"[-2, 12]")) - t1 := (-2).I - val u1 = 0.U(3.W) - val r1 = RegInit(u1) - r1 := u1 - val t2 = t1.wrap(u1) - val t3 = t1.wrap(r1) - - assert( - t2.range.upper == Closed(7), - s"t1 upper ${t2.range.upper} expected ${Closed(7)}" - ) - assert( - t3.range.upper == Closed(7), - s"t1 upper ${t3.range.upper} expected ${Closed(7)}" - ) - - val in1 = WireInit(Interval(range"[0,9].6"), 0.I) - val in2 = WireInit(Interval(range"[1,6).4"), 2.I) - val in3 = in1.wrap(in2) - - assert( - in3.range.lower == Closed(1), - s"in3 lower ${in3.range.lower} expected ${Closed(1)}" - ) - assert( - in3.range.upper == Open(6), - s"in3 upper ${in3.range.upper} expected ${Open(6)}" - ) - assert( - in3.binaryPoint == KnownBinaryPoint(6), - s"in3 binaryPoint ${in3.binaryPoint} expected ${KnownBinaryPoint(2)}" - ) - - val enclosedRange = range"[-2, 5]" - val base = Wire(Interval(range"[-4, 6]")) - val enclosed = WireInit(Interval(enclosedRange), 0.I) - val enclosing = WireInit(Interval(range"[-6, 8]"), 0.I) - val overlapLeft = WireInit(Interval(range"[-10,-2]"), (-3).I) - val overlapRight = WireInit(Interval(range"[-1,10]"), 0.I) - - val w1 = base.wrap(enclosed) - val w2 = base.wrap(enclosing) - val w3 = base.wrap(overlapLeft) - val w4 = base.wrap(overlapRight) - val w7 = base.wrap(enclosedRange) - - base := 6.I - - assert(w1 === (-2).I) - assert(w2 === 6.I) - assert(w3 === (-3).I) - assert(w4 === 6.I) - assert(w7 === (-2).I) - - stop() -} - -class IntervalClipTester extends BasicTester { - - val enclosedRange = range"[-2, 5]" - val base = Wire(Interval(range"[-4, 6]")) - val enclosed = Wire(Interval(enclosedRange)) - val enclosing = Wire(Interval(range"[-6, 8]")) - val overlapLeft = Wire(Interval(range"[-10,-2]")) - val overlapRight = Wire(Interval(range"[-1,10]")) - val disjointLeft = Wire(Interval(range"[-14,-7]")) - val disjointRight = Wire(Interval(range"[7,11]")) - - enclosed := DontCare - enclosing := DontCare - overlapLeft := DontCare - overlapRight := DontCare - disjointLeft := DontCare - disjointRight := DontCare - - val enclosedResult = base.clip(enclosed) - val enclosingResult = base.clip(enclosing) - val overlapLeftResult = base.clip(overlapLeft) - val overlapRightResult = base.clip(overlapRight) - val disjointLeftResult = base.clip(disjointLeft) - val disjointRightResult = base.clip(disjointRight) - val enclosedViaRangeString = base.clip(enclosedRange) - - base := 6.I - - assert(enclosedResult === 5.I) - assert(enclosingResult === 6.I) - assert(overlapLeftResult === (-2).I) - assert(overlapRightResult === 6.I) - assert(disjointLeftResult === (-7).I) - assert(disjointRightResult === 7.I) - - assert(enclosedViaRangeString === 5.I) - - stop() -} - -class IntervalChainedAddTester extends BasicTester { - - val intervalResult = Wire(Interval()) - val uintResult = Wire(UInt()) - - intervalResult := 1.I + 1.I + 1.I + 1.I + 1.I + 1.I + 1.I - uintResult := 1.U +& 1.U +& 1.U +& 1.U +& 1.U +& 1.U +& 1.U - - assert(intervalResult === 7.I) - assert(uintResult === 7.U) - stop() -} - -class IntervalChainedMulTester extends BasicTester { - - val intervalResult = Wire(Interval()) - val uintResult = Wire(UInt()) - - intervalResult := 2.I * 2.I * 2.I * 2.I * 2.I * 2.I * 2.I - uintResult := 2.U * 2.U * 2.U * 2.U * 2.U * 2.U * 2.U - - assert(intervalResult === 128.I) - assert(uintResult === 128.U) - stop() -} - -class IntervalChainedSubTester extends BasicTester { - val intervalResult1 = Wire(Interval()) - val intervalResult2 = Wire(Interval()) - val uIntResult = Wire(UInt()) - val sIntResult = Wire(SInt()) - val fixedResult = Wire(FixedPoint()) - - intervalResult1 := 17.I - 2.I - 2.I - 2.I - 2.I - 2.I - 2.I // gives same result as -& operand version below - intervalResult2 := 17.I -& 2.I -& 2.I -& 2.I -& 2.I -& 2.I -& 2.I - uIntResult := 17.U -& 2.U -& 2.U -& 2.U -& 2.U -& 2.U -& 2.U - fixedResult := 17.0.F(0.BP) -& 2.0.F(0.BP) -& 2.0.F(0.BP) -& 2.0.F(0.BP) -& 2.0 - .F(0.BP) -& 2.0.F(0.BP) -& 2.0.F(0.BP) - sIntResult := 17.S -& 2.S -& 2.S -& 2.S -& 2.S -& 2.S -& 2.S - - assert(uIntResult === 5.U) - assert(sIntResult === 5.S) - assert(fixedResult.asUInt === 5.U) - assert(intervalResult1 === 5.I) - assert(intervalResult2 === 5.I) - - val negativeInterval = (-3.5).I(4.BP) - val positiveInterval = 3.5.I(4.BP) - - assert(negativeInterval =/= positiveInterval) - assert(-negativeInterval === positiveInterval) - assert(negativeInterval === -positiveInterval) - - stop() -} - -//TODO: need tests for dynamic shifts on intervals -class IntervalSpec extends AnyFreeSpec with Matchers with ChiselRunners { - - type TempFirrtlException = Exception - - "Test a simple interval add" in { - assertTesterPasses { new IntervalAddTester } - } - "Intervals can be created" in { - assertTesterPasses { new IntervalTester } - } - "Test a simple interval mux" in { - assertTesterPasses { new IntervalTester2 } - } - "Intervals can have binary points set" in { - assertTesterPasses { new IntervalSetBinaryPointTester } - } - "Interval literals that don't fit in explicit ranges are caught by chisel" - { - "case 1: does not fit in specified width" in { - intercept[ChiselException] { - ChiselGeneratorAnnotation(() => - new BasicTester { - val x = 5.I(3.W, 0.BP) - } - ).elaborate - } - } - "case 2: doesn't fit in specified range" in { - intercept[ChiselException] { - ChiselGeneratorAnnotation(() => - new BasicTester { - val x = 5.I(range"[0,4]") - } - ).elaborate - } - } - } - - "Interval literals support to double and to BigDecimal" in { - val d = -7.125 - val lit1 = d.I(3.BP) - lit1.litToDouble should be(d) - - val d2 = BigDecimal("1232123213131123.125") - val lit2 = d2.I(3.BP) - lit2.litToBigDecimal should be(d2) - - // Numbers that are too big will throw exception - intercept[ChiselException] { - lit2.litToDouble - } - } - - "Interval literals creation handles edge cases" - { - "value at closed boundaries works" in { - val inputRange = range"[-6, 6].2" - val in1 = (-6.0).I(inputRange) - val in2 = 6.0.I(inputRange) - BigDecimal(in1.litValue()) / (1 << inputRange.binaryPoint.get) should be(-6) - BigDecimal(in2.litValue()) / (1 << inputRange.binaryPoint.get) should be(6) - intercept[ChiselException] { - (-6.25).I(inputRange) - } - intercept[ChiselException] { - (6.25).I(inputRange) - } - } - "value at open boundaries works" in { - val inputRange = range"(-6, 6).2" - val in1 = (-5.75).I(inputRange) - val in2 = 5.75.I(inputRange) - BigDecimal(in1.litValue()) / (1 << inputRange.binaryPoint.get) should be(-5.75) - BigDecimal(in2.litValue()) / (1 << inputRange.binaryPoint.get) should be(5.75) - intercept[ChiselException] { - (-6.0).I(inputRange) - } - intercept[ChiselException] { - (6.0).I(inputRange) - } - } - "values not precisely at open boundaries works but are converted to nearest match" in { - val inputRange = range"(-6, 6).2" - val in1 = (-5.95).I(inputRange) - val in2 = 5.95.I(inputRange) - BigDecimal(in1.litValue()) / (1 << inputRange.binaryPoint.get) should be(-5.75) - BigDecimal(in2.litValue()) / (1 << inputRange.binaryPoint.get) should be(5.75) - intercept[ChiselException] { - (-6.1).I(inputRange) - } - intercept[ChiselException] { - (6.1).I(inputRange) - } - } - } - - "Let's take a look at the results of squeeze over small range" in { - assertTesterPasses { - new ClipSqueezeWrapDemo( - range = range"[-10,33].0", - targetRange = range"[-4,17].0", - startNum = -4.0, - endNum = 30.0, - incNum = 1.0 - ) - } - assertTesterPasses { - new ClipSqueezeWrapDemo( - range = range"[-2,5].1", - targetRange = range"[-1,3].1", - startNum = -2.0, - endNum = 5.0, - incNum = 0.5 - ) - } - } - "Intervals can be squeezed into another intervals range" in { - assertTesterPasses { - new SqueezeFunctionalityTester( - range"[-2,5]", - BigDecimal(-10), - BigDecimal(10), - BigDecimal(1.0) - ) - } - } - "Intervals can be wrapped with wrap operator" in { - assertTesterPasses { new IntervalWrapTester } - } - - "Interval compile pathologies: clip, wrap, and squeeze have different behavior" - { - "wrap target range is completely left of source" in { - intercept[TempFirrtlException] { - assertTesterPasses(new BasicTester { - val base = Wire(Interval(range"[-4, 6]")) - base := 6.I - val disjointLeft = WireInit(Interval(range"[-7,-5]"), (-6).I) - val w5 = base.wrap(disjointLeft) - stop() - }) - } - } - "wrap target range is completely right of source" in { - intercept[TempFirrtlException] { - assertTesterPasses(new BasicTester { - val base = Wire(Interval(range"[-4, 6]")) - base := 6.I - val disjointLeft = WireInit(Interval(range"[7,10]"), 8.I) - val w5 = base.wrap(disjointLeft) - stop() - }) - } - } - "clip target range is completely left of source" in { - assertTesterPasses(new BasicTester { - val base = Wire(Interval(range"[-4, 6]")) - base := 6.I - val disjointLeft = WireInit(Interval(range"[-7,-5]"), (-6).I) - val w5 = base.clip(disjointLeft) - chisel3.assert(w5 === (-5).I) - stop() - }) - } - "clip target range is completely right of source" in { - assertTesterPasses(new BasicTester { - val base = Wire(Interval(range"[-4, 6]")) - base := 6.I - val disjointLeft = WireInit(Interval(range"[7,10]"), 8.I) - val w5 = base.clip(disjointLeft) - chisel3.assert(w5.asSInt === 7.S) - stop() - }) - } - "squeeze target range is completely right of source" in { - intercept[TempFirrtlException] { - assertTesterPasses(new BasicTester { - val base = Wire(Interval(range"[-4, 6]")) - base := 6.I - val disjointLeft = WireInit(Interval(range"[7,10]"), 8.I) - val w5 = base.squeeze(disjointLeft) - chisel3.assert(w5.asSInt === 6.S) - stop() - }) - } - } - "squeeze target range is completely left of source" in { - intercept[TempFirrtlException] { - assertTesterPasses(new BasicTester { - val base = Wire(Interval(range"[-4, 6]")) - base := 6.I - val disjointLeft = WireInit(Interval(range"[-7, -5]"), 8.I) - val w5 = base.squeeze(disjointLeft) - stop() - }) - } - } - - def makeCircuit(operation: String, sourceRange: IntervalRange, targetRange: IntervalRange): () => RawModule = { - () => - new Module { - val io = IO(new Bundle { val out = Output(Interval()) }) - val base = Wire(Interval(sourceRange)) - base := 6.I - - val disjointLeft = WireInit(Interval(targetRange), 8.I) - val w5 = operation match { - case "clip" => base.clip(disjointLeft) - case "wrap" => base.wrap(disjointLeft) - case "squeeze" => base.squeeze(disjointLeft) - } - io.out := w5 - } - } - - "disjoint ranges should error when used with clip, wrap and squeeze" - { - - def mustGetException(disjointLeft: Boolean, operation: String): Boolean = { - val (rangeA, rangeB) = if (disjointLeft) { - (range"[-4, 6]", range"[7,10]") - } else { - (range"[7,10]", range"[-4, 6]") - } - try { - makeFirrtl("low")(makeCircuit(operation, rangeA, rangeB)) - false - } catch { - case _: InvalidConnect | _: PassExceptions | _: InvalidRange | _: WrapWithRemainder | _: DisjointSqueeze => - true - case _: Throwable => - false - } - } - - "Range A disjoint left, operation clip should generate useful error" in { - mustGetException(disjointLeft = true, "clip") should be(false) - } - "Range A largely out of bounds left, operation wrap should generate useful error" in { - mustGetException(disjointLeft = true, "wrap") should be(true) - } - "Range A disjoint left, operation squeeze should generate useful error" in { - mustGetException(disjointLeft = true, "squeeze") should be(true) - } - "Range A disjoint right, operation clip should generate useful error" in { - mustGetException(disjointLeft = false, "clip") should be(true) - } - "Range A disjoint right, operation wrap should generate useful error" in { - mustGetException(disjointLeft = false, "wrap") should be(true) - } - "Range A disjoint right, operation squeeze should generate useful error" in { - mustGetException(disjointLeft = false, "squeeze") should be(true) - } - } - - "Errors are sometimes inconsistent or incorrectly labelled as Firrtl Internal Error" - { - "squeeze disjoint is not internal error when defined in BasicTester" in { - intercept[DisjointSqueeze] { - makeFirrtl("low")(() => - new BasicTester { - val base = Wire(Interval(range"[-4, 6]")) - val base2 = Wire(Interval(range"[-4, 6]")) - base := 6.I - base2 := 5.I - val disjointLeft = WireInit(Interval(range"[7,10]"), 8.I) - val w5 = base.squeeze(disjointLeft) - stop() - } - ) - } - } - "wrap disjoint is not internal error when defined in BasicTester" in { - intercept[DisjointSqueeze] { - makeFirrtl("low")(() => - new BasicTester { - val base = Wire(Interval(range"[-4, 6]")) - val base2 = Wire(Interval(range"[-4, 6]")) - base := 6.I - base2 := 5.I - val disjointLeft = WireInit(Interval(range"[7,10]"), 8.I) - val w5 = base.squeeze(disjointLeft) - stop() - } - ) - } - } - "squeeze disjoint from Module gives exception" in { - intercept[DisjointSqueeze] { - makeFirrtl("low")(() => - new Module { - val io = IO(new Bundle { - val out = Output(Interval()) - }) - val base = Wire(Interval(range"[-4, 6]")) - base := 6.I - - val disjointLeft = WireInit(Interval(range"[7,10]"), 8.I) - val w5 = base.squeeze(disjointLeft) - io.out := w5 - } - ) - } - } - "clip disjoint from Module gives no error" in { - makeFirrtl("low")(() => - new Module { - val io = IO(new Bundle { - val out = Output(Interval()) - }) - val base = Wire(Interval(range"[-4, 6]")) - base := 6.I - - val disjointLeft = WireInit(Interval(range"[7,10]"), 8.I) - val w5 = base.clip(disjointLeft) - io.out := w5 - } - ) - } - "wrap disjoint from Module wrap with remainder" in { - intercept[WrapWithRemainder] { - makeFirrtl("low")(() => - new Module { - val io = IO(new Bundle { - val out = Output(Interval()) - }) - val base = Wire(Interval(range"[-4, 6]")) - base := 6.I - - val disjointLeft = WireInit(Interval(range"[7,10]"), 8.I) - val w5 = base.wrap(disjointLeft) - io.out := w5 - } - ) - } - } - } - - "assign literal out of range of interval" in { - intercept[firrtl.passes.CheckTypes.InvalidConnect] { - assertTesterPasses(new BasicTester { - val base = Wire(Interval(range"[-4, 6]")) - base := (-8).I - }) - } - } - } - - "Intervals should catch assignment of literals outside of range" - { - "when literal is too small" in { - intercept[InvalidConnect] { - makeFirrtl("low")(() => - new Module { - val io = IO(new Bundle { val out = Output(Interval()) }) - val base = Wire(Interval(range"[-4, 6]")) - base := (-7).I - io.out := base - } - ) - } - } - "when literal is too big" in { - intercept[InvalidConnect] { - makeFirrtl("low")(() => - new Module { - val io = IO(new Bundle { val out = Output(Interval()) }) - val base = Wire(Interval(range"[-4, 6]")) - base := 9.I - io.out := base - } - ) - } - } - } - - "Intervals can be shifted left" in { - assertTesterPasses(new BasicTester { - val i1 = 3.0.I(range"[0,4]") - val shifted1 = i1 << 2 - val shiftUInt = WireInit(1.U(8.W)) - val shifted2 = i1 << shiftUInt - - chisel3.assert(shifted1 === 12.I, "shifted 1 should be 12, it wasn't") - chisel3.assert(shifted2 === 6.I, "shifted 2 should be 6 it wasn't") - stop() - }) - } - - "Intervals can be shifted right" in { - assertTesterPasses(new BasicTester { - val i1 = 12.0.I(range"[0,15]") - val shifted1 = i1 >> 2 - val shiftUInt = 1.U - val shifted2 = i1 >> shiftUInt - - chisel3.assert(shifted1 === 3.I) - chisel3.assert(shifted2 === 6.I) - stop() - }) - } - - "Intervals can be used to construct registers" in { - assertTesterPasses { new IntervalRegisterTester } - } - "Intervals can be clipped with clip (saturate) operator" in { - assertTesterPasses { new IntervalClipTester } - } - "Intervals adds same answer as UInt" in { - assertTesterPasses { new IntervalChainedAddTester } - } - "Intervals should produce canonically smaller ranges via inference" in { - val loFirrtl = makeFirrtl("low")(() => - new Module { - val io = IO(new Bundle { - val in = Input(Interval(range"[0,1]")) - val out = Output(Interval()) - }) - - val intervalResult = Wire(Interval()) - - intervalResult := 1.I + 1.I + 1.I + 1.I + 1.I + 1.I + 1.I - io.out := intervalResult - } - ) - loFirrtl.contains("output io_out : SInt<4>") should be(true) - - } - "Intervals multiplication same answer as UInt" in { - assertTesterPasses { new IntervalChainedMulTester } - } - "Intervals subs same answer as UInt" in { - assertTesterPasses { new IntervalChainedSubTester } - } - "Test clip, wrap and a variety of ranges" - { - """range"[0.0,10.0].2" => range"[2,6].2"""" in { - assertTesterPasses(new BasicTester { - - val sourceRange = range"[0.0,10.0].2" - val targetRange = range"[2,6].2" - - val sourceSimulator = ScalaIntervalSimulator(sourceRange) - val targetSimulator = ScalaIntervalSimulator(targetRange) - - for (sourceValue <- sourceSimulator.allValues) { - val clippedValue = Wire(Interval(targetRange)) - clippedValue := sourceSimulator - .makeLit(sourceValue) - .clip(clippedValue) - - val goldClippedValue = - targetSimulator.makeLit(targetSimulator.clip(sourceValue)) - - // Useful for debugging - // printf(s"source value $sourceValue clipped gold value %d compare to clipped value %d\n", - // goldClippedValue.asSInt(), clippedValue.asSInt()) - - chisel3.assert(goldClippedValue === clippedValue) - - val wrappedValue = Wire(Interval(targetRange)) - wrappedValue := sourceSimulator - .makeLit(sourceValue) - .wrap(wrappedValue) - - val goldWrappedValue = - targetSimulator.makeLit(targetSimulator.wrap(sourceValue)) - - // Useful for debugging - // printf(s"source value $sourceValue wrapped gold value %d compare to wrapped value %d\n", - // goldWrappedValue.asSInt(), wrappedValue.asSInt()) - - chisel3.assert(goldWrappedValue === wrappedValue) - } - - stop() - }) - } - } - - "Test squeeze over a variety of ranges" - { - """range"[2,6].2""" in { - assertTesterPasses(new BasicTester { - - val sourceRange = range"[0.0,10.0].2" - val targetRange = range"[2,6].3" - - val sourceSimulator = ScalaIntervalSimulator(sourceRange) - val targetSimulator = ScalaIntervalSimulator(targetRange) - - for (sourceValue <- sourceSimulator.allValues) { - val squeezedValue = Wire(Interval(targetRange)) - squeezedValue := sourceSimulator - .makeLit(sourceValue) - .clip(squeezedValue) - - val goldSqueezedValue = - targetSimulator.makeLit(targetSimulator.clip(sourceValue)) - - // Useful for debugging - // printf(s"source value $sourceValue squeezed gold value %d compare to squeezed value %d\n", - // goldSqueezedValue.asSInt(), squeezedValue.asSInt()) - - chisel3.assert(goldSqueezedValue === squeezedValue) - } - - stop() - }) - } - } - - "test asInterval" - { - "use with UInt" in { - assertTesterPasses(new BasicTester { - val u1 = Wire(UInt(5.W)) - u1 := 7.U - val i1 = u1.asInterval(range"[0,15]") - val i2 = u1.asInterval(range"[0,15].2") - printf("i1 %d\n", i1.asUInt) - chisel3.assert(i1 === 7.I, "i1") - stop() - }) - } - "use with SInt" in { - assertTesterPasses(new BasicTester { - val s1 = Wire(SInt(5.W)) - s1 := 7.S - val s2 = Wire(SInt(5.W)) - s2 := 7.S - val i1 = s1.asInterval(range"[-16,15]") - val i2 = s1.asInterval(range"[-16,15].1") - printf("i1 %d\n", i1.asSInt) - printf("i2 %d\n", i2.asSInt) - chisel3.assert(i1 === 7.I, "i1 is wrong") - chisel3.assert(i2 === (3.5).I(binaryPoint = 1.BP), "i2 is wrong") - stop() - }) - } - "more SInt tests" in { - assertTesterPasses(new BasicTester { - chisel3.assert(7.S.asInterval(range"[-16,15].1") === 3.5.I(binaryPoint = 1.BP), "adding binary point") - stop() - }) - } - } -} diff --git a/src/test/scala/chiselTests/InvalidateAPISpec.scala b/src/test/scala/chiselTests/InvalidateAPISpec.scala deleted file mode 100644 index dbd353a0..00000000 --- a/src/test/scala/chiselTests/InvalidateAPISpec.scala +++ /dev/null @@ -1,239 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} -import chisel3.util.Counter -import firrtl.passes.CheckInitialization.RefNotInitializedException -import firrtl.util.BackendCompilationUtilities -import org.scalatest._ -import org.scalatest.matchers.should.Matchers - -class InvalidateAPISpec extends ChiselPropSpec with Matchers with BackendCompilationUtilities with Utils { - - def myGenerateFirrtl(t: => Module): String = ChiselStage.emitChirrtl(t) - def compileFirrtl(t: => Module): Unit = { - val testDir = createTestDirectory(this.getClass.getSimpleName) - - (new ChiselStage).execute( - Array[String]("-td", testDir.getAbsolutePath, "--compiler", "verilog"), - Seq(ChiselGeneratorAnnotation(() => t)) - ) - } - class TrivialInterface extends Bundle { - val in = Input(Bool()) - val out = Output(Bool()) - } - - property("an output connected to DontCare should emit a Firrtl \"is invalid\" with Strict CompileOptions") { - import chisel3.ExplicitCompileOptions.Strict - class ModuleWithDontCare extends Module { - val io = IO(new TrivialInterface) - io.out := DontCare - io.out := io.in - } - val firrtlOutput = myGenerateFirrtl(new ModuleWithDontCare) - firrtlOutput should include("io.out is invalid") - } - - property("an output without a DontCare should NOT emit a Firrtl \"is invalid\" with Strict CompileOptions") { - import chisel3.ExplicitCompileOptions.Strict - class ModuleWithoutDontCare extends Module { - val io = IO(new TrivialInterface) - io.out := io.in - } - val firrtlOutput = myGenerateFirrtl(new ModuleWithoutDontCare) - (firrtlOutput should not).include("is invalid") - } - - property("an output without a DontCare should emit a Firrtl \"is invalid\" with NotStrict CompileOptions") { - import chisel3.ExplicitCompileOptions.NotStrict - class ModuleWithoutDontCare extends Module { - val io = IO(new TrivialInterface) - io.out := io.in - } - val firrtlOutput = myGenerateFirrtl(new ModuleWithoutDontCare) - firrtlOutput should include("io is invalid") - } - - property("a bundle with a DontCare should emit a Firrtl \"is invalid\" with Strict CompileOptions") { - import chisel3.ExplicitCompileOptions.Strict - class ModuleWithoutDontCare extends Module { - val io = IO(new TrivialInterface) - io <> DontCare - } - val firrtlOutput = myGenerateFirrtl(new ModuleWithoutDontCare) - firrtlOutput should include("io.out is invalid") - firrtlOutput should include("io.in is invalid") - } - - property("a Vec with a DontCare should emit a Firrtl \"is invalid\" with Strict CompileOptions and bulk connect") { - import chisel3.ExplicitCompileOptions.Strict - val nElements = 5 - class ModuleWithoutDontCare extends Module { - val io = IO(new Bundle { - val outs = Output(Vec(nElements, Bool())) - }) - io.outs <> DontCare - } - val firrtlOutput = myGenerateFirrtl(new ModuleWithoutDontCare) - for (i <- 0 until nElements) - firrtlOutput should include(s"io.outs[$i] is invalid") - } - - property("a Vec with a DontCare should emit a Firrtl \"is invalid\" with Strict CompileOptions and mono connect") { - import chisel3.ExplicitCompileOptions.Strict - val nElements = 5 - class ModuleWithoutDontCare extends Module { - val io = IO(new Bundle { - val ins = Input(Vec(nElements, Bool())) - }) - io.ins := DontCare - } - val firrtlOutput = myGenerateFirrtl(new ModuleWithoutDontCare) - for (i <- 0 until nElements) - firrtlOutput should include(s"io.ins[$i] is invalid") - } - - property("a DontCare cannot be a connection sink (LHS) for := ") { - import chisel3.ExplicitCompileOptions.Strict - class ModuleWithDontCareSink extends Module { - val io = IO(new TrivialInterface) - DontCare := io.in - } - val exception = intercept[ChiselException] { - extractCause[ChiselException] { - ChiselStage.elaborate(new ModuleWithDontCareSink) - } - } - exception.getMessage should include("DontCare cannot be a connection sink") - } - - property("a DontCare cannot be a connection sink (LHS) for <>") { - import chisel3.ExplicitCompileOptions.Strict - class ModuleWithDontCareSink extends Module { - val io = IO(new TrivialInterface) - DontCare <> io.in - } - val exception = intercept[BiConnectException] { - extractCause[BiConnectException] { - ChiselStage.elaborate(new ModuleWithDontCareSink) - } - } - exception.getMessage should include("DontCare cannot be a connection sink (LHS)") - } - - property("FIRRTL should complain about partial initialization with Strict CompileOptions and conditional connect") { - import chisel3.ExplicitCompileOptions.Strict - class ModuleWithIncompleteAssignment extends Module { - val io = IO(new Bundle { - val out = Output(Bool()) - }) - val counter = Counter(8) - when(counter.inc()) { - io.out := true.B - } - } - val exception = intercept[RefNotInitializedException] { - compileFirrtl(new ModuleWithIncompleteAssignment) - } - exception.getMessage should include("is not fully initialized") - } - - property( - "FIRRTL should not complain about partial initialization with Strict CompileOptions and conditional connect after unconditional connect" - ) { - import chisel3.ExplicitCompileOptions.Strict - class ModuleWithUnconditionalAssignment extends Module { - val io = IO(new Bundle { - val out = Output(Bool()) - }) - val counter = Counter(8) - io.out := false.B - when(counter.inc()) { - io.out := true.B - } - } - compileFirrtl(new ModuleWithUnconditionalAssignment) - } - - property( - "FIRRTL should not complain about partial initialization with Strict CompileOptions and conditional connect with otherwise clause" - ) { - import chisel3.ExplicitCompileOptions.Strict - class ModuleWithConditionalAndOtherwiseAssignment extends Module { - val io = IO(new Bundle { - val out = Output(Bool()) - }) - val counter = Counter(8) - when(counter.inc()) { - io.out := true.B - }.otherwise { - io.out := false.B - } - } - - compileFirrtl(new ModuleWithConditionalAndOtherwiseAssignment) - } - - property( - "an output without a DontCare should NOT emit a Firrtl \"is invalid\" with overriden NotStrict CompileOptions" - ) { - import chisel3.ExplicitCompileOptions.NotStrict - class ModuleWithoutDontCare extends Module { - override val compileOptions = chisel3.ExplicitCompileOptions.NotStrict.copy(explicitInvalidate = true) - val io = IO(new TrivialInterface) - io.out := io.in - } - val firrtlOutput = myGenerateFirrtl(new ModuleWithoutDontCare) - (firrtlOutput should not).include("is invalid") - } - - property( - "an output without a DontCare should NOT emit a Firrtl \"is invalid\" with overriden NotStrict CompileOptions module definition" - ) { - import chisel3.ExplicitCompileOptions.NotStrict - abstract class ExplicitInvalidateModule - extends Module()(chisel3.ExplicitCompileOptions.NotStrict.copy(explicitInvalidate = true)) - class ModuleWithoutDontCare extends ExplicitInvalidateModule { - val io = IO(new TrivialInterface) - io.out := io.in - } - val firrtlOutput = myGenerateFirrtl(new ModuleWithoutDontCare) - (firrtlOutput should not).include("is invalid") - } - - property("an output without a DontCare should emit a Firrtl \"is invalid\" with overriden Strict CompileOptions") { - import chisel3.ExplicitCompileOptions.Strict - class ModuleWithoutDontCare extends Module { - override val compileOptions = chisel3.ExplicitCompileOptions.Strict.copy(explicitInvalidate = false) - val io = IO(new TrivialInterface) - io.out := io.in - } - val firrtlOutput = myGenerateFirrtl(new ModuleWithoutDontCare) - firrtlOutput should include("is invalid") - } - - property( - "an output without a DontCare should emit a Firrtl \"is invalid\" with overriden Strict CompileOptions module definition" - ) { - import chisel3.ExplicitCompileOptions.Strict - abstract class ImplicitInvalidateModule - extends Module()(chisel3.ExplicitCompileOptions.NotStrict.copy(explicitInvalidate = false)) - class ModuleWithoutDontCare extends ImplicitInvalidateModule { - val io = IO(new TrivialInterface) - io.out := io.in - } - val firrtlOutput = myGenerateFirrtl(new ModuleWithoutDontCare) - firrtlOutput should include("is invalid") - } - - property("a clock should be able to be connected to a DontCare") { - class ClockConnectedToDontCare extends Module { - val foo = IO(Output(Clock())) - foo := DontCare - } - myGenerateFirrtl(new ClockConnectedToDontCare) should include("foo is invalid") - } -} diff --git a/src/test/scala/chiselTests/LiteralExtractorSpec.scala b/src/test/scala/chiselTests/LiteralExtractorSpec.scala deleted file mode 100644 index 3906057f..00000000 --- a/src/test/scala/chiselTests/LiteralExtractorSpec.scala +++ /dev/null @@ -1,158 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.experimental._ -import chisel3.experimental.BundleLiterals._ -import chisel3.stage.ChiselStage -import chisel3.testers.BasicTester -import scala.collection.immutable.ListMap - -class LiteralExtractorSpec extends ChiselFlatSpec { - "litValue" should "return the literal value" in { - assert(0.U.litValue === BigInt(0)) - assert(1.U.litValue === BigInt(1)) - assert(42.U.litValue === BigInt(42)) - assert(42.U.litValue === 42.U.litValue) - - assert(0.S.litValue === BigInt(0)) - assert(-1.S.litValue === BigInt(-1)) - assert(-42.S.litValue === BigInt(-42)) - - assert(true.B.litValue === BigInt(1)) - assert(false.B.litValue === BigInt(0)) - - assert(1.25.F(2.BP).litValue === BigInt("101", 2)) - assert(2.25.F(2.BP).litValue === BigInt("1001", 2)) - - assert(-1.25.F(2.BP).litValue === BigInt("-101", 2)) - assert(-2.25.F(2.BP).litValue === BigInt("-1001", 2)) - } - - "litToBoolean" should "return the literal value" in { - assert(true.B.litToBoolean === true) - assert(false.B.litToBoolean === false) - - assert(1.B.litToBoolean === true) - assert(0.B.litToBoolean === false) - } - - "litToDouble" should "return the literal value" in { - assert(1.25.F(2.BP).litToDouble == 1.25) - assert(2.25.F(2.BP).litToDouble == 2.25) - - assert(-1.25.F(2.BP).litToDouble == -1.25) - assert(-2.25.F(2.BP).litToDouble == -2.25) - - // test rounding - assert(1.24.F(1.BP).litToDouble == 1.0) - assert(1.25.F(1.BP).litToDouble == 1.5) - } - - "litOption" should "return None for non-literal hardware" in { - ChiselStage.elaborate { - new RawModule { - val a = Wire(UInt()) - assert(a.litOption == None) - } - } - } - - "doubles and big decimals" should "round trip properly" in { - intercept[ChiselException] { - Num.toBigDecimal(BigInt("1" * 109, 2), 0.BP) // this only works if number takes less than 109 bits - } - - intercept[ChiselException] { - Num.toDouble(BigInt("1" * 54, 2), 0.BP) // this only works if number takes less than 54 bits - } - - val bigInt108 = BigInt("1" * 108, 2) - val bigDecimal = Num.toBigDecimal(bigInt108, 2) - - val bigIntFromBigDecimal = Num.toBigInt(bigDecimal, 2) - - bigIntFromBigDecimal should be(bigInt108) - - val bigInt53 = BigInt("1" * 53, 2) - - val double = Num.toDouble(bigInt53, 2) - - val bigIntFromDouble = Num.toBigInt(double, 2) - - bigIntFromDouble should be(bigInt53) - } - - "encoding and decoding of Intervals" should "round trip" in { - val rangeMin = BigDecimal(-31.5) - val rangeMax = BigDecimal(32.5) - val range = range"($rangeMin, $rangeMax).2" - for (value <- (rangeMin - 4) to (rangeMax + 4) by 2.25) { - if (value < rangeMin || value > rangeMax) { - intercept[ChiselException] { - val literal = value.I(range) - } - } else { - val literal = value.I(range) - literal.isLit() should be(true) - literal.litValue().toDouble / 4.0 should be(value) - } - } - } - - "literals declared outside a builder context" should "compare with those inside builder context" in { - class InsideBundle extends Bundle { - val x = SInt(8.W) - val y = FixedPoint(8.W, 4.BP) - } - - class LitInsideOutsideTester(outsideLiteral: InsideBundle) extends BasicTester { - val insideLiteral = (new InsideBundle).Lit(_.x -> 7.S, _.y -> 6.125.F(4.BP)) - - // the following errors with "assertion failed" - - println(outsideLiteral === insideLiteral) - // chisel3.assert(outsideLiteral === insideLiteral) - - // the following lines of code error - // with "chisel3.internal.BundleLitBinding cannot be cast to chisel3.internal.ElementLitBinding" - - chisel3.assert(outsideLiteral.x === insideLiteral.x) - chisel3.assert(outsideLiteral.y === insideLiteral.y) - chisel3.assert(outsideLiteral.x === 7.S) - chisel3.assert(outsideLiteral.y === 6.125.F(4.BP)) - - stop() - } - - val outsideLiteral = (new InsideBundle).Lit(_.x -> 7.S, _.y -> 6.125.F(4.BP)) - assertTesterPasses { new LitInsideOutsideTester(outsideLiteral) } - - } - - "bundle literals" should "do the right thing" in { - class MyBundle extends Bundle { - val a = UInt(8.W) - val b = Bool() - } - val myBundleLiteral = (new MyBundle).Lit(_.a -> 42.U, _.b -> true.B) - assert(myBundleLiteral.a.litValue == 42) - assert(myBundleLiteral.b.litValue == 1) - assert(myBundleLiteral.b.litToBoolean == true) - } - - "record literals" should "do the right thing" in { - class MyRecord extends Record { - override val elements = ListMap( - "a" -> UInt(8.W), - "b" -> Bool() - ) - override def cloneType = (new MyRecord).asInstanceOf[this.type] - } - - val myRecordLiteral = new (MyRecord).Lit(_.elements("a") -> 42.U, _.elements("b") -> true.B) - assert(myRecordLiteral.elements("a").litValue == 42) - assert(myRecordLiteral.elements("b").litValue == 1) - } -} diff --git a/src/test/scala/chiselTests/LiteralToTargetSpec.scala b/src/test/scala/chiselTests/LiteralToTargetSpec.scala deleted file mode 100644 index b1caecfa..00000000 --- a/src/test/scala/chiselTests/LiteralToTargetSpec.scala +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage - -import org.scalatest._ -import org.scalatest.freespec.AnyFreeSpec -import org.scalatest.matchers.should.Matchers - -class LiteralToTargetSpec extends AnyFreeSpec with Matchers { - - "Literal Data should fail to be converted to ReferenceTarget" in { - - (the[chisel3.internal.ChiselException] thrownBy { - - class Bar extends RawModule { - val a = 1.U - } - - class Foo extends RawModule { - val bar = Module(new Bar) - bar.a.toTarget - } - - ChiselStage.elaborate(new Foo) - } should have).message("Illegal component name: UInt<1>(\"h01\") (note: literals are illegal)") - } -} diff --git a/src/test/scala/chiselTests/LoadMemoryFromFileSpec.scala b/src/test/scala/chiselTests/LoadMemoryFromFileSpec.scala deleted file mode 100644 index 8e5e48b4..00000000 --- a/src/test/scala/chiselTests/LoadMemoryFromFileSpec.scala +++ /dev/null @@ -1,270 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import java.io.File - -import chisel3._ -import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} -import chisel3.util.experimental.{loadMemoryFromFile, loadMemoryFromFileInline} -import chisel3.util.log2Ceil -import firrtl.annotations.MemoryLoadFileType -import org.scalatest.freespec.AnyFreeSpec -import org.scalatest.matchers.should.Matchers - -class UsesThreeMems(memoryDepth: Int, memoryType: Data) extends Module { - val io = IO(new Bundle { - val address = Input(UInt(memoryType.getWidth.W)) - val value1 = Output(memoryType) - val value2 = Output(memoryType) - val value3 = Output(memoryType) - }) - - val memory1 = Mem(memoryDepth, memoryType) - val memory2 = Mem(memoryDepth, memoryType) - val memory3 = Mem(memoryDepth, memoryType) - loadMemoryFromFile(memory1, "./mem1") - loadMemoryFromFile(memory2, "./mem1") - loadMemoryFromFile(memory3, "./mem1") - - io.value1 := memory1(io.address) - io.value2 := memory2(io.address) - io.value3 := memory3(io.address) -} - -class UsesThreeMemsInline( - memoryDepth: Int, - memoryType: Data, - memoryFile: String, - hexOrBinary: MemoryLoadFileType.FileType) - extends Module { - val io = IO(new Bundle { - val address = Input(UInt(memoryType.getWidth.W)) - val value1 = Output(memoryType) - val value2 = Output(memoryType) - val value3 = Output(memoryType) - }) - - val memory1 = Mem(memoryDepth, memoryType) - val memory2 = Mem(memoryDepth, memoryType) - val memory3 = Mem(memoryDepth, memoryType) - loadMemoryFromFileInline(memory1, memoryFile, hexOrBinary) - loadMemoryFromFileInline(memory2, memoryFile, hexOrBinary) - loadMemoryFromFileInline(memory3, memoryFile, hexOrBinary) - - io.value1 := memory1(io.address) - io.value2 := memory2(io.address) - io.value3 := memory3(io.address) -} - -class UsesMem(memoryDepth: Int, memoryType: Data) extends Module { - val io = IO(new Bundle { - val address = Input(UInt(memoryType.getWidth.W)) - val value = Output(memoryType) - val value1 = Output(memoryType) - val value2 = Output(memoryType) - }) - - val memory = Mem(memoryDepth, memoryType) - loadMemoryFromFile(memory, "./mem1") - - io.value := memory(io.address) - - val low1 = Module(new UsesMemLow(memoryDepth, memoryType)) - val low2 = Module(new UsesMemLow(memoryDepth, memoryType)) - - low2.io.address := io.address - low1.io.address := io.address - io.value1 := low1.io.value - io.value2 := low2.io.value -} - -class UsesMemLow(memoryDepth: Int, memoryType: Data) extends Module { - val io = IO(new Bundle { - val address = Input(UInt(memoryType.getWidth.W)) - val value = Output(memoryType) - }) - - val memory = Mem(memoryDepth, memoryType) - - loadMemoryFromFile(memory, "./mem2") - - io.value := memory(io.address) -} - -class FileHasSuffix(memoryDepth: Int, memoryType: Data) extends Module { - val io = IO(new Bundle { - val address = Input(UInt(memoryType.getWidth.W)) - val value = Output(memoryType) - val value2 = Output(memoryType) - }) - - val memory = Mem(memoryDepth, memoryType) - - loadMemoryFromFile(memory, "./mem1.txt") - - io.value := memory(io.address) - - val low = Module(new UsesMemLow(memoryDepth, memoryType)) - - low.io.address := io.address - io.value2 := low.io.value -} - -class MemoryShape extends Bundle { - val a = UInt(8.W) - val b = SInt(8.W) - val c = Bool() -} - -class HasComplexMemory(memoryDepth: Int) extends Module { - val io = IO(new Bundle { - val address = Input(UInt(log2Ceil(memoryDepth).W)) - val value = Output(new MemoryShape) - }) - - val memory = Mem(memoryDepth, new MemoryShape) - - loadMemoryFromFile(memory, "./mem", MemoryLoadFileType.Hex) - - io.value := memory(io.address) -} - -class HasBinarySupport(memoryDepth: Int, memoryType: Data) extends Module { - val io = IO(new Bundle { - val address = Input(UInt(memoryType.getWidth.W)) - val value = Output(memoryType) - }) - - val memory = Mem(memoryDepth, memoryType) - - loadMemoryFromFile(memory, "./mem", MemoryLoadFileType.Binary) - - io.value := memory(io.address) -} - -/** - * The following tests are a bit incomplete and check that the output verilog is properly constructed - * For more complete working examples - * @see <a href="https://github.com/freechipsproject/chisel-testers">Chisel Testers</a> LoadMemoryFromFileSpec.scala - */ -class LoadMemoryFromFileSpec extends AnyFreeSpec with Matchers { - def fileExistsWithMem(file: File, mem: Option[String] = None): Unit = { - info(s"$file exists") - file.exists() should be(true) - mem.foreach(m => { - info(s"Memory $m is referenced in $file") - val found = io.Source.fromFile(file).getLines.exists { _.contains(s"""readmemh("$m"""") } - found should be(true) - }) - file.delete() - } - - "Users can specify a source file to load memory from" in { - val testDirName = "test_run_dir/load_memory_spec" - - val result = (new ChiselStage).execute( - args = Array("-X", "verilog", "--target-dir", testDirName), - annotations = Seq(ChiselGeneratorAnnotation(() => new UsesMem(memoryDepth = 8, memoryType = UInt(16.W)))) - ) - - val dir = new File(testDirName) - fileExistsWithMem(new File(dir, "UsesMem.UsesMem.memory.v"), Some("./mem1")) - fileExistsWithMem(new File(dir, "UsesMem.UsesMemLow.memory.v"), Some("./mem2")) - fileExistsWithMem(new File(dir, "firrtl_black_box_resource_files.f")) - - } - - "Calling a module that loads memories from a file more than once should work" in { - val testDirName = "test_run_dir/load_three_memory_spec" - - val result = (new ChiselStage).execute( - args = Array("-X", "verilog", "--target-dir", testDirName), - annotations = Seq(ChiselGeneratorAnnotation(() => new UsesThreeMems(memoryDepth = 8, memoryType = UInt(16.W)))) - ) - - val dir = new File(testDirName) - fileExistsWithMem(new File(dir, "UsesThreeMems.UsesThreeMems.memory1.v"), Some("./mem1")) - fileExistsWithMem(new File(dir, "UsesThreeMems.UsesThreeMems.memory2.v"), Some("./mem1")) - fileExistsWithMem(new File(dir, "UsesThreeMems.UsesThreeMems.memory3.v"), Some("./mem1")) - fileExistsWithMem(new File(dir, "firrtl_black_box_resource_files.f")) - - } - - "In this example the memory has a complex memory type containing a bundle" in { - val complexTestDirName = "test_run_dir/complex_memory_load" - - val result = (new ChiselStage).execute( - args = Array("-X", "verilog", "--target-dir", complexTestDirName), - annotations = Seq(ChiselGeneratorAnnotation(() => new HasComplexMemory(memoryDepth = 8))) - ) - - val dir = new File(complexTestDirName) - val memoryElements = Seq("a", "b", "c") - - memoryElements.foreach { element => - val file = new File(dir, s"HasComplexMemory.HasComplexMemory.memory_$element.v") - file.exists() should be(true) - val fileText = io.Source.fromFile(file).getLines().mkString("\n") - fileText should include(s"""$$readmemh("./mem_$element", HasComplexMemory.memory_$element);""") - file.delete() - } - - } - - "Has binary format support" in { - val testDirName = "test_run_dir/binary_memory_load" - - val result = (new ChiselStage).execute( - args = Array("-X", "verilog", "--target-dir", testDirName), - annotations = Seq(ChiselGeneratorAnnotation(() => new HasBinarySupport(memoryDepth = 8, memoryType = UInt(16.W)))) - ) - - val dir = new File(testDirName) - val file = new File(dir, s"HasBinarySupport.HasBinarySupport.memory.v") - file.exists() should be(true) - val fileText = io.Source.fromFile(file).getLines().mkString("\n") - fileText should include(s"""$$readmemb("./mem", HasBinarySupport.memory);""") - file.delete() - } - - "Module with more than one hex memory inline should work" in { - val testDirName = "test_run_dir/load_three_memory_spec_inline" - - val result = (new ChiselStage).execute( - args = Array("-X", "verilog", "--target-dir", testDirName), - annotations = Seq( - ChiselGeneratorAnnotation(() => - new UsesThreeMemsInline(memoryDepth = 8, memoryType = UInt(16.W), "./testmem.h", MemoryLoadFileType.Hex) - ) - ) - ) - val dir = new File(testDirName) - val file = new File(dir, s"UsesThreeMemsInline.v") - file.exists() should be(true) - val fileText = io.Source.fromFile(file).getLines().mkString("\n") - fileText should include(s"""$$readmemh("./testmem.h", memory1);""") - fileText should include(s"""$$readmemh("./testmem.h", memory2);""") - fileText should include(s"""$$readmemh("./testmem.h", memory3);""") - } - - "Module with more than one bin memory inline should work" in { - val testDirName = "test_run_dir/load_three_memory_spec_inline" - - val result = (new ChiselStage).execute( - args = Array("-X", "verilog", "--target-dir", testDirName), - annotations = Seq( - ChiselGeneratorAnnotation(() => - new UsesThreeMemsInline(memoryDepth = 8, memoryType = UInt(16.W), "testmem.bin", MemoryLoadFileType.Binary) - ) - ) - ) - val dir = new File(testDirName) - val file = new File(dir, s"UsesThreeMemsInline.v") - file.exists() should be(true) - val fileText = io.Source.fromFile(file).getLines().mkString("\n") - fileText should include(s"""$$readmemb("testmem.bin", memory1);""") - fileText should include(s"""$$readmemb("testmem.bin", memory2);""") - fileText should include(s"""$$readmemb("testmem.bin", memory3);""") - } -} diff --git a/src/test/scala/chiselTests/Math.scala b/src/test/scala/chiselTests/Math.scala deleted file mode 100644 index 42eff6ad..00000000 --- a/src/test/scala/chiselTests/Math.scala +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import org.scalacheck.Shrink - -class Math extends ChiselPropSpec { - import chisel3.util._ - // Disable shrinking on error. - implicit val noShrinkListVal = Shrink[List[Int]](_ => Stream.empty) - implicit val noShrinkInt = Shrink[Int](_ => Stream.empty) - - property("unsignedBitLength is computed correctly") { - forAll(safeUIntWidth) { - case (width: Int) => - for (offset <- List(-1, 0, 1)) { - val n = (1 << width) + offset - if (n >= 0) { - val d = unsignedBitLength(n) - val t = if (n == 0) 0 else if (offset < 0) width else width + 1 - d shouldEqual (t) - } - } - } - } - - property("signedBitLength is computed correctly") { - forAll(safeUIntWidth) { - case (width: Int) => - for (offset <- List(-1, 0, 1)) { - for (mult <- List(-1, +1)) { - val n = ((1 << (width - 1)) + offset) * mult - val d = signedBitLength(n) - val t = n match { - case -2 => 2 - case -1 => 1 - case 0 => 0 - case 1 => 2 - case 2 => 3 - case _ => - if (n > 0) { - if (offset < 0) width else width + 1 - } else { - if (offset > 0) width + 1 else width - } - } - d shouldEqual (t) - } - } - } - } -} diff --git a/src/test/scala/chiselTests/Mem.scala b/src/test/scala/chiselTests/Mem.scala deleted file mode 100644 index c5fcc6b1..00000000 --- a/src/test/scala/chiselTests/Mem.scala +++ /dev/null @@ -1,241 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.util._ -import chisel3.testers.BasicTester - -class MemVecTester extends BasicTester { - val mem = Mem(2, Vec(2, UInt(8.W))) - - // Circuit style tester is definitely the wrong abstraction here - val (cnt, wrap) = Counter(true.B, 2) - mem(0)(0) := 1.U - - when(cnt === 1.U) { - assert(mem.read(0.U)(0) === 1.U) - stop() - } -} - -class SyncReadMemTester extends BasicTester { - val (cnt, _) = Counter(true.B, 5) - val mem = SyncReadMem(2, UInt(2.W)) - val rdata = mem.read(cnt - 1.U, cnt =/= 0.U) - - switch(cnt) { - is(0.U) { mem.write(cnt, 3.U) } - is(1.U) { mem.write(cnt, 2.U) } - is(2.U) { assert(rdata === 3.U) } - is(3.U) { assert(rdata === 2.U) } - is(4.U) { stop() } - } -} - -class SyncReadMemWriteCollisionTester extends BasicTester { - val (cnt, _) = Counter(true.B, 5) - - // Write-first - val m0 = SyncReadMem(2, UInt(2.W), SyncReadMem.WriteFirst) - val rd0 = m0.read(cnt) - m0.write(cnt, cnt) - - // Read-first - val m1 = SyncReadMem(2, UInt(2.W), SyncReadMem.ReadFirst) - val rd1 = m1.read(cnt) - m1.write(cnt, cnt) - - // Read data from address 0 - when(cnt === 3.U) { - assert(rd0 === 2.U) - assert(rd1 === 0.U) - } - - when(cnt === 4.U) { - stop() - } -} - -class SyncReadMemWithZeroWidthTester extends BasicTester { - val (cnt, _) = Counter(true.B, 3) - val mem = SyncReadMem(2, UInt(0.W)) - val rdata = mem.read(0.U, true.B) - - switch(cnt) { - is(1.U) { assert(rdata === 0.U) } - is(2.U) { stop() } - } -} - -// TODO this can't actually simulate with FIRRTL behavioral mems -class HugeSMemTester(size: BigInt) extends BasicTester { - val (cnt, _) = Counter(true.B, 5) - val mem = SyncReadMem(size, UInt(8.W)) - val rdata = mem.read(cnt - 1.U, cnt =/= 0.U) - - switch(cnt) { - is(0.U) { mem.write(cnt, 3.U) } - is(1.U) { mem.write(cnt, 2.U) } - is(2.U) { assert(rdata === 3.U) } - is(3.U) { assert(rdata === 2.U) } - is(4.U) { stop() } - } -} -class HugeCMemTester(size: BigInt) extends BasicTester { - val (cnt, _) = Counter(true.B, 5) - val mem = Mem(size, UInt(8.W)) - val rdata = mem.read(cnt) - - switch(cnt) { - is(0.U) { mem.write(cnt, 3.U) } - is(1.U) { mem.write(cnt, 2.U) } - is(2.U) { assert(rdata === 3.U) } - is(3.U) { assert(rdata === 2.U) } - is(4.U) { stop() } - } -} - -class SyncReadMemBundleTester extends BasicTester { - val (cnt, _) = Counter(true.B, 5) - val tpe = new Bundle { - val foo = UInt(2.W) - } - val mem = SyncReadMem(2, tpe) - val rdata = mem.read(cnt - 1.U, cnt =/= 0.U) - - switch(cnt) { - is(0.U) { - val w = Wire(tpe) - w.foo := 3.U - mem.write(cnt, w) - } - is(1.U) { - val w = Wire(tpe) - w.foo := 2.U - mem.write(cnt, w) - } - is(2.U) { assert(rdata.foo === 3.U) } - is(3.U) { assert(rdata.foo === 2.U) } - is(4.U) { stop() } - } -} - -class MemBundleTester extends BasicTester { - val tpe = new Bundle { - val foo = UInt(2.W) - } - val mem = Mem(2, tpe) - - // Circuit style tester is definitely the wrong abstraction here - val (cnt, wrap) = Counter(true.B, 2) - mem(0) := { - val w = Wire(tpe) - w.foo := 1.U - w - } - - when(cnt === 1.U) { - assert(mem.read(0.U).foo === 1.U) - stop() - } -} - -private class TrueDualPortMemoryIO(val addrW: Int, val dataW: Int) extends Bundle { - require(addrW > 0, "address width must be greater than 0") - require(dataW > 0, "data width must be greater than 0") - - val clka = Input(Clock()) - val ena = Input(Bool()) - val wea = Input(Bool()) - val addra = Input(UInt(addrW.W)) - val dia = Input(UInt(dataW.W)) - val doa = Output(UInt(dataW.W)) - - val clkb = Input(Clock()) - val enb = Input(Bool()) - val web = Input(Bool()) - val addrb = Input(UInt(addrW.W)) - val dib = Input(UInt(dataW.W)) - val dob = Output(UInt(dataW.W)) -} - -private class TrueDualPortMemory(addrW: Int, dataW: Int) extends RawModule { - val io = IO(new TrueDualPortMemoryIO(addrW, dataW)) - val ram = SyncReadMem(1 << addrW, UInt(dataW.W)) - - // Port a - withClock(io.clka) { - io.doa := DontCare - when(io.ena) { - when(io.wea) { - ram(io.addra) := io.dia - } - io.doa := ram(io.addra) - } - } - - // Port b - withClock(io.clkb) { - io.dob := DontCare - when(io.enb) { - when(io.web) { - ram(io.addrb) := io.dib - } - io.dob := ram(io.addrb) - } - } -} - -class MemorySpec extends ChiselPropSpec { - property("Mem of Vec should work") { - assertTesterPasses { new MemVecTester } - } - - property("SyncReadMem should work") { - assertTesterPasses { new SyncReadMemTester } - } - - property("SyncReadMems of Bundles should work") { - assertTesterPasses { new SyncReadMemBundleTester } - } - - property("Mems of Bundles should work") { - assertTesterPasses { new MemBundleTester } - } - - property("SyncReadMem write collision behaviors should work") { - assertTesterPasses { new SyncReadMemWriteCollisionTester } - } - - property("SyncReadMem should work with zero width entry") { - assertTesterPasses { new SyncReadMemWithZeroWidthTester } - } - - property("Massive memories should be emitted in Verilog") { - val addrWidth = 65 - val size = BigInt(1) << addrWidth - val smem = compile(new HugeSMemTester(size)) - smem should include(s"reg /* sparse */ [7:0] mem [0:$addrWidth'd${size - 1}];") - val cmem = compile(new HugeCMemTester(size)) - cmem should include(s"reg /* sparse */ [7:0] mem [0:$addrWidth'd${size - 1}];") - } - - property("Implicit conversions with Mem indices should work") { - """ - |import chisel3._ - |import chisel3.util.ImplicitConversions._ - |class MyModule extends Module { - | val io = IO(new Bundle {}) - | val mem = Mem(32, UInt(8.W)) - | mem(0) := 0.U - |} - |""".stripMargin should compile - } - - property("memories in modules without implicit clock should compile without warning or error") { - val stage = new ChiselStage - stage.emitVerilog(new TrueDualPortMemory(4, 32)) - } -} diff --git a/src/test/scala/chiselTests/MemorySearch.scala b/src/test/scala/chiselTests/MemorySearch.scala deleted file mode 100644 index df1c6b32..00000000 --- a/src/test/scala/chiselTests/MemorySearch.scala +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage - -class MemorySearch extends Module { - val io = IO(new Bundle { - val target = Input(UInt(4.W)) - val en = Input(Bool()) - val done = Output(Bool()) - val address = Output(UInt(3.W)) - }) - val vals = Array(0, 4, 15, 14, 2, 5, 13) - val index = RegInit(0.U(3.W)) - val elts = VecInit(vals.map(_.asUInt(4.W))) - // val elts = Mem(UInt(32.W), 8) TODO ???? - val elt = elts(index) - val end = !io.en && ((elt === io.target) || (index === 7.U)) - when(io.en) { - index := 0.U - }.elsewhen(!end) { - index := index +% 1.U - } - io.done := end - io.address := index -} - -/* -class MemorySearchTester(c: MemorySearch) extends Tester(c) { - val list = c.vals - val n = 8 - val maxT = n * (list.length + 3) - for (k <- 0 until n) { - val target = rnd.nextInt(16) - poke(c.io.en, 1) - poke(c.io.target, target) - step(1) - poke(c.io.en, 0) - do { - step(1) - } while (peek(c.io.done) == 0 && t < maxT) - val addr = peek(c.io.address).toInt - expect(addr == list.length || list(addr) == target, - "LOOKING FOR " + target + " FOUND " + addr) - } -} - */ - -class MemorySearchSpec extends ChiselPropSpec { - - property("MemorySearch should elaborate") { - ChiselStage.elaborate { new EnableShiftRegister } - } - - ignore("MemorySearch should return the correct result") {} -} diff --git a/src/test/scala/chiselTests/MigrateCompileOptionsSpec.scala b/src/test/scala/chiselTests/MigrateCompileOptionsSpec.scala deleted file mode 100644 index 091f7f28..00000000 --- a/src/test/scala/chiselTests/MigrateCompileOptionsSpec.scala +++ /dev/null @@ -1,133 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3.stage.ChiselStage -import chisel3.ImplicitInvalidate -import chisel3.ExplicitCompileOptions - -import org.scalatestplus.scalacheck.ScalaCheckDrivenPropertyChecks - -object MigrationExamples { - object InferResets { - import Chisel.{defaultCompileOptions => _, _} - import chisel3.RequireSyncReset - implicit val migrateIR = new chisel3.CompileOptions { - val connectFieldsMustMatch = false - val declaredTypeMustBeUnbound = false - val dontTryConnectionsSwapped = false - val dontAssumeDirectionality = false - val checkSynthesizable = false - val explicitInvalidate = false - val inferModuleReset = false - - override val migrateInferModuleReset = true - } - - class Foo extends Module { - val io = new Bundle {} - } - class FooWithRequireSyncReset extends Module with RequireSyncReset { - val io = new Bundle {} - } - } - object ExplicitInvalidate { - import chisel3.ImplicitInvalidate - val migrateEI = new chisel3.CompileOptions { - val connectFieldsMustMatch = false - val declaredTypeMustBeUnbound = false - val dontTryConnectionsSwapped = false - val dontAssumeDirectionality = false - val checkSynthesizable = false - val explicitInvalidate = true - val inferModuleReset = false - } - object ChiselChildren { - import Chisel.{defaultCompileOptions => _, _} - implicit val options = migrateEI - class Foo extends Module { - val io = new Bundle { - val out = Output(UInt(width = 3)) - } - } - class FooWithImplicitInvalidate extends Module with ImplicitInvalidate { - val io = new Bundle { - val out = Output(UInt(width = 3)) - } - } - class FooWire extends Module { - val io = new Bundle {} - val wire = Wire(Bool()) - } - class FooWireWithImplicitInvalidate extends Module with ImplicitInvalidate { - val io = new Bundle {} - val wire = Wire(Bool()) - } - } - object chisel3Children { - import chisel3._ - class Foo extends Module { - val in = IO(chisel3.Input(UInt(3.W))) - } - } - object ChiselParents { - import Chisel.{defaultCompileOptions => _, _} - implicit val options = migrateEI - - class FooParent extends Module { - val io = new Bundle {} - val i = Module(new chisel3Children.Foo) - } - class FooParentWithImplicitInvalidate extends Module with ImplicitInvalidate { - val io = new Bundle {} - val i = Module(new chisel3Children.Foo) - } - } - } -} - -class MigrateCompileOptionsSpec extends ChiselFunSpec with Utils { - import Chisel.{defaultCompileOptions => _, _} - import chisel3.RequireSyncReset - - describe("(0): Migrating infer resets") { - import MigrationExamples.InferResets._ - it("(0.a): Error if migrating, but not extended RequireSyncReset") { - intercept[Exception] { ChiselStage.elaborate(new Foo) } - } - it("(0.b): Not error if migrating, and you mix with RequireSyncReset") { - ChiselStage.elaborate(new FooWithRequireSyncReset) - } - } - - describe("(1): Migrating explicit invalidate") { - import MigrationExamples.ExplicitInvalidate._ - - it("(1.a): error if migrating module input, but not extending ImplicitInvalidate") { - intercept[_root_.firrtl.passes.CheckInitialization.RefNotInitializedException] { - ChiselStage.emitVerilog(new ChiselChildren.Foo) - } - } - it("(1.b): succeed if migrating module input with extending ImplicitInvalidate") { - ChiselStage.emitVerilog(new ChiselChildren.FooWithImplicitInvalidate) - } - - it("(1.c): error if migrating instance output, but not extending ImplicitInvalidate") { - intercept[_root_.firrtl.passes.CheckInitialization.RefNotInitializedException] { - ChiselStage.emitVerilog(new ChiselParents.FooParent) - } - } - it("(1.d): succeed if migrating instance output with extending ImplicitInvalidate") { - ChiselStage.emitVerilog(new ChiselParents.FooParentWithImplicitInvalidate) - } - - it("(1.e): error if migrating wire declaration, but not extending ImplicitInvalidate") { - intercept[_root_.firrtl.passes.CheckInitialization.RefNotInitializedException] { - ChiselStage.emitVerilog(new ChiselChildren.FooWire) - } - } - it("(1.f): succeed if migrating wire declaration with extending ImplicitInvalidate") { - ChiselStage.emitVerilog(new ChiselChildren.FooWireWithImplicitInvalidate) - } - } -} diff --git a/src/test/scala/chiselTests/MixedVecSpec.scala b/src/test/scala/chiselTests/MixedVecSpec.scala deleted file mode 100644 index ee19d653..00000000 --- a/src/test/scala/chiselTests/MixedVecSpec.scala +++ /dev/null @@ -1,299 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.testers.BasicTester -import chisel3.util._ -import org.scalacheck.Shrink - -class MixedVecAssignTester(w: Int, values: List[Int]) extends BasicTester { - val v = MixedVecInit(values.map(v => v.U(w.W))) - for ((a, b) <- v.zip(values)) { - assert(a === b.asUInt) - } - stop() -} - -class MixedVecRegTester(w: Int, values: List[Int]) extends BasicTester { - val valuesInit = MixedVecInit(values.map(v => v.U(w.W))) - val reg = Reg(MixedVec(chiselTypeOf(valuesInit))) - - val doneReg = RegInit(false.B) - doneReg := true.B - - when(!doneReg) { - // First cycle: write to reg - reg := valuesInit - }.otherwise { - // Second cycle: read back from reg - for ((a, b) <- reg.zip(values)) { - assert(a === b.asUInt) - } - stop() - } -} - -class MixedVecIOPassthroughModule[T <: Data](hvec: MixedVec[T]) extends Module { - val io = IO(new Bundle { - val in = Input(hvec) - val out = Output(hvec) - }) - io.out := io.in -} - -class MixedVecIOTester(boundVals: Seq[Data]) extends BasicTester { - val v = MixedVecInit(boundVals) - val dut = Module(new MixedVecIOPassthroughModule(MixedVec(chiselTypeOf(v)))) - dut.io.in := v - for ((a, b) <- dut.io.out.zip(boundVals)) { - assert(a.asUInt === b.asUInt) - } - stop() -} - -class MixedVecZeroEntryTester extends BasicTester { - def zeroEntryMixedVec: MixedVec[Data] = MixedVec(Seq.empty) - - require(zeroEntryMixedVec.getWidth == 0) - - val bundleWithZeroEntryVec = new Bundle { - val foo = Bool() - val bar = zeroEntryMixedVec - } - require(0.U.asTypeOf(bundleWithZeroEntryVec).getWidth == 1) - require(bundleWithZeroEntryVec.asUInt.getWidth == 1) - - val m = Module(new Module { - val io = IO(Output(bundleWithZeroEntryVec)) - io.foo := false.B - }) - WireDefault(m.io.bar) - - stop() -} - -class MixedVecUIntDynamicIndexTester extends BasicTester { - val wire = Wire(MixedVec(Seq(UInt(8.W), UInt(16.W), UInt(4.W), UInt(7.W)))) - val n = wire.length - - for (i <- 0 until n) { - wire(i) := i.U - } - - val vecWire = VecInit(wire.toSeq) - - val (cycle, done) = Counter(true.B, n) - assert(vecWire(cycle) === cycle) - - when(done) { stop() } -} - -class MixedVecTestBundle extends Bundle { - val x = UInt(8.W) - val y = UInt(8.W) -} - -class MixedVecSmallTestBundle extends Bundle { - val x = UInt(3.W) - val y = UInt(3.W) -} - -class MixedVecFromVecTester extends BasicTester { - val wire = Wire(MixedVec(Vec(3, UInt(8.W)))) - wire := MixedVecInit(Seq(20.U, 40.U, 80.U)) - - assert(wire(0) === 20.U) - assert(wire(1) === 40.U) - assert(wire(2) === 80.U) - - stop() -} - -class MixedVecConnectWithVecTester extends BasicTester { - val mixedVecType = MixedVec(Vec(3, UInt(8.W))) - - val m = Module(new MixedVecIOPassthroughModule(mixedVecType)) - m.io.in := VecInit(Seq(20.U, 40.U, 80.U)) - val wire = m.io.out - - assert(wire(0) === 20.U) - assert(wire(1) === 40.U) - assert(wire(2) === 80.U) - - stop() -} - -class MixedVecConnectWithSeqTester extends BasicTester { - val mixedVecType = MixedVec(Vec(3, UInt(8.W))) - - val m = Module(new MixedVecIOPassthroughModule(mixedVecType)) - m.io.in := Seq(20.U, 40.U, 80.U) - val wire = m.io.out - - assert(wire(0) === 20.U) - assert(wire(1) === 40.U) - assert(wire(2) === 80.U) - - stop() -} - -class MixedVecOneBitTester extends BasicTester { - val flag = RegInit(false.B) - - val oneBit = Reg(MixedVec(Seq(UInt(1.W)))) - when(!flag) { - oneBit(0) := 1.U(1.W) - flag := true.B - }.otherwise { - assert(oneBit(0) === 1.U) - assert(oneBit.asUInt === 1.U) - stop() - } -} - -class MixedVecSpec extends ChiselPropSpec with Utils { - // Disable shrinking on error. - // Not sure why this needs to be here, but the test behaves very weirdly without it (e.g. empty Lists, etc). - implicit val noShrinkListVal = Shrink[List[Int]](_ => Stream.empty) - implicit val noShrinkInt = Shrink[Int](_ => Stream.empty) - - property("MixedVec varargs API should work") { - assertTesterPasses { - new BasicTester { - val wire = Wire(MixedVec(UInt(1.W), UInt(8.W))) - wire(0) := 1.U - wire(1) := 101.U - - chisel3.assert(wire(0) === 1.U) - chisel3.assert(wire(1) + 1.U === 102.U) - - val wireInit = MixedVecInit(1.U, 101.U) - chisel3.assert(wireInit(0) === 1.U) - chisel3.assert(wireInit(1) + 1.U === 102.U) - - stop() - } - } - } - - property("MixedVecs should be assignable") { - forAll(safeUIntN(8)) { - case (w: Int, v: List[Int]) => - assertTesterPasses { - new MixedVecAssignTester(w, v) - } - } - } - - property("MixedVecs should be usable as the type for Reg()") { - forAll(safeUIntN(8)) { - case (w: Int, v: List[Int]) => - assertTesterPasses { - new MixedVecRegTester(w, v) - } - } - } - - property("MixedVecs should be passed through IO") { - forAll(safeUIntN(8)) { - case (w: Int, v: List[Int]) => - assertTesterPasses { - new MixedVecIOTester(v.map(i => i.U(w.W))) - } - } - } - - property("MixedVecs should work with mixed types") { - assertTesterPasses { - new MixedVecIOTester(Seq(true.B, 168.U(8.W), 888.U(10.W), -3.S)) - } - } - - property("MixedVecs should not be able to take hardware types") { - a[ExpectedChiselTypeException] should be thrownBy extractCause[ExpectedChiselTypeException] { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle {}) - val hw = Wire(MixedVec(Seq(UInt(8.W), Bool()))) - val illegal = MixedVec(hw) - }) - } - a[ExpectedChiselTypeException] should be thrownBy extractCause[ExpectedChiselTypeException] { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle {}) - val hw = Reg(MixedVec(Seq(UInt(8.W), Bool()))) - val illegal = MixedVec(hw) - }) - } - a[ExpectedChiselTypeException] should be thrownBy extractCause[ExpectedChiselTypeException] { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val v = Input(MixedVec(Seq(UInt(8.W), Bool()))) - }) - val illegal = MixedVec(io.v) - }) - } - } - - property("MixedVecs with zero entries should compile and have zero width") { - assertTesterPasses { new MixedVecZeroEntryTester } - } - - property("MixedVecs of UInts should be dynamically indexable (via VecInit)") { - assertTesterPasses { new MixedVecUIntDynamicIndexTester } - } - - property("MixedVecs should be creatable from Vecs") { - assertTesterPasses { new MixedVecFromVecTester } - } - - property("It should be possible to bulk connect a MixedVec and a Vec") { - assertTesterPasses { new MixedVecConnectWithVecTester } - } - - property("It should be possible to bulk connect a MixedVec and a Seq") { - assertTesterPasses { new MixedVecConnectWithSeqTester } - } - - property("MixedVecs of a single 1 bit element should compile and work") { - assertTesterPasses { new MixedVecOneBitTester } - } - - property("Connecting a MixedVec and something of different size should report a ChiselException") { - an[IllegalArgumentException] should be thrownBy extractCause[IllegalArgumentException] { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val out = Output(MixedVec(Seq(UInt(8.W), Bool()))) - }) - val seq = Seq.fill(5)(0.U) - io.out := seq - }) - } - an[IllegalArgumentException] should be thrownBy extractCause[IllegalArgumentException] { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val out = Output(MixedVec(Seq(UInt(8.W), Bool()))) - }) - val seq = VecInit(Seq(100.U(8.W))) - io.out := seq - }) - } - } - - property("MixedVec connections should emit FIRRTL bulk connects when possible") { - val chirrtl = ChiselStage.emitChirrtl(new Module { - val io = IO(new Bundle { - val inMono = Input(MixedVec(Seq(UInt(8.W), UInt(16.W), UInt(4.W), UInt(7.W)))) - val outMono = Output(MixedVec(Seq(UInt(8.W), UInt(16.W), UInt(4.W), UInt(7.W)))) - val inBi = Input(MixedVec(Seq(UInt(8.W), UInt(16.W), UInt(4.W), UInt(7.W)))) - val outBi = Output(MixedVec(Seq(UInt(8.W), UInt(16.W), UInt(4.W), UInt(7.W)))) - }) - // Explicit upcast avoids weird issue where Scala 2.12 overloading resolution calls version of := accepting Seq[T] instead of normal Data version - io.outMono := (io.inMono: Data) - io.outBi <> io.inBi - }) - chirrtl should include("io.outMono <= io.inMono @[MixedVecSpec.scala") - chirrtl should include("io.outBi <= io.inBi @[MixedVecSpec.scala") - } -} diff --git a/src/test/scala/chiselTests/Module.scala b/src/test/scala/chiselTests/Module.scala deleted file mode 100644 index b0fece3b..00000000 --- a/src/test/scala/chiselTests/Module.scala +++ /dev/null @@ -1,286 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.experimental.DataMirror -import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage, NoRunFirrtlCompilerAnnotation} -import firrtl.annotations.NoTargetAnnotation -import firrtl.options.Unserializable - -import scala.io.Source -import scala.annotation.nowarn - -class SimpleIO extends Bundle { - val in = Input(UInt(32.W)) - val out = Output(UInt(32.W)) -} - -class PlusOne extends Module { - val io = IO(new SimpleIO) - val myReg = RegInit(0.U(8.W)) - dontTouch(myReg) - io.out := io.in + 1.asUInt -} - -class ModuleVec(val n: Int) extends Module { - val io = IO(new Bundle { - val ins = Input(Vec(n, UInt(32.W))) - val outs = Output(Vec(n, UInt(32.W))) - }) - val pluses = VecInit(Seq.fill(n) { Module(new PlusOne).io }) - for (i <- 0 until n) { - pluses(i).in := io.ins(i) - io.outs(i) := pluses(i).out - } -} - -class ModuleWire extends Module { - val io = IO(new SimpleIO) - val inc = Wire(chiselTypeOf(Module(new PlusOne).io)) - inc.in := io.in - io.out := inc.out -} - -class ModuleWhen extends Module { - val io = IO(new Bundle { - val s = new SimpleIO - val en = Output(Bool()) - }) - when(io.en) { - val inc = Module(new PlusOne).io - inc.in := io.s.in - io.s.out := inc.out - }.otherwise { io.s.out := io.s.in } -} - -class ModuleForgetWrapper extends Module { - val io = IO(new SimpleIO) - val inst = new PlusOne -} - -class ModuleDoubleWrap extends Module { - val io = IO(new SimpleIO) - val inst = Module(Module(new PlusOne)) -} - -class ModuleRewrap extends Module { - val io = IO(new SimpleIO) - val inst = Module(new PlusOne) - val inst2 = Module(inst) -} - -class ModuleWrapper(gen: => Module) extends Module { - val io = IO(new Bundle {}) - val child = Module(gen) - override val desiredName = s"${child.desiredName}Wrapper" -} - -class NullModuleWrapper extends Module { - val io = IO(new Bundle {}) - override lazy val desiredName = s"${child.desiredName}Wrapper" - println(s"My name is ${name}") - val child = Module(new ModuleWire) -} - -class ModuleSpec extends ChiselPropSpec with Utils { - - property("ModuleVec should elaborate") { - ChiselStage.elaborate { new ModuleVec(2) } - } - - ignore("ModuleVecTester should return the correct result") {} - - property("ModuleWire should elaborate") { - ChiselStage.elaborate { new ModuleWire } - } - - ignore("ModuleWireTester should return the correct result") {} - - property("ModuleWhen should elaborate") { - ChiselStage.elaborate { new ModuleWhen } - } - - ignore("ModuleWhenTester should return the correct result") {} - - property("Forgetting a Module() wrapper should result in an error") { - (the[ChiselException] thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { new ModuleForgetWrapper } - }).getMessage should include("attempted to instantiate a Module without wrapping it") - } - - property("Double wrapping a Module should result in an error") { - (the[ChiselException] thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { new ModuleDoubleWrap } - }).getMessage should include("Called Module() twice without instantiating a Module") - } - - property("Rewrapping an already instantiated Module should result in an error") { - (the[ChiselException] thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { new ModuleRewrap } - }).getMessage should include("This is probably due to rewrapping a Module instance") - } - - property("object Module.clock should return a reference to the currently in scope clock") { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val clock2 = Input(Clock()) - }) - assert(Module.clock eq this.clock) - withClock(io.clock2) { assert(Module.clock eq io.clock2) } - }) - } - property("object Module.reset should return a reference to the currently in scope reset") { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val reset2 = Input(Bool()) - }) - assert(Module.reset eq this.reset) - withReset(io.reset2) { assert(Module.reset eq io.reset2) } - }) - } - property("object Module.currentModule should return an Option reference to the current Module") { - def checkModule(mod: Module): Boolean = Module.currentModule.map(_ eq mod).getOrElse(false) - ChiselStage.elaborate(new Module { - val io = IO(new Bundle {}) - assert(Module.currentModule.get eq this) - assert(checkModule(this)) - }) - } - - property("object chisel3.util.experimental.getAnnotations should return current annotations.") { - case class DummyAnnotation() extends NoTargetAnnotation with Unserializable - (new ChiselStage).transform( - Seq( - ChiselGeneratorAnnotation(() => - new RawModule { - assert(chisel3.util.experimental.getAnnotations().contains(DummyAnnotation())) - } - ), - DummyAnnotation(), - NoRunFirrtlCompilerAnnotation - ) - ) - } - - property("DataMirror.modulePorts should work") { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle {}) - val m = Module(new chisel3.Module { - val a = IO(UInt(8.W)) - val b = IO(Bool()) - }) - assert(DataMirror.modulePorts(m) == Seq("clock" -> m.clock, "reset" -> m.reset, "a" -> m.a, "b" -> m.b)) - }) - } - - property("DataMirror.modulePorts should replace deprecated <module>.getPorts") { - class MyModule extends Module { - val io = IO(new Bundle { - val in = Input(UInt(8.W)) - val out = Output(Vec(2, UInt(8.W))) - }) - val extra = IO(Input(UInt(8.W))) - val delay = RegNext(io.in) - io.out(0) := delay - io.out(1) := delay + extra - } - var mod: MyModule = null - ChiselStage.elaborate { - mod = new MyModule - mod - } - // Note that this is just top-level ports, Aggregates are not flattened - (DataMirror.modulePorts(mod) should contain).theSameElementsInOrderAs( - Seq( - "clock" -> mod.clock, - "reset" -> mod.reset, - "io" -> mod.io, - "extra" -> mod.extra - ) - ) - // Delete this when the deprecated API is deleted - // Note this also uses deprecated Port - import chisel3.internal.firrtl.Port - import SpecifiedDirection.{Input => IN, Unspecified} - (mod.getPorts should contain).theSameElementsInOrderAs( - Seq( - Port(mod.clock, IN), - Port(mod.reset, IN), - Port(mod.io, Unspecified), - Port(mod.extra, IN) - ) - ): @nowarn // delete when Port and getPorts become private - } - - property("DataMirror.fullModulePorts should return all ports including children of Aggregates") { - class MyModule extends Module { - val io = IO(new Bundle { - val in = Input(UInt(8.W)) - val out = Output(Vec(2, UInt(8.W))) - }) - val extra = IO(Input(UInt(8.W))) - val delay = RegNext(io.in) - io.out(0) := delay - io.out(1) := delay + extra - } - var mod: MyModule = null - ChiselStage.elaborate { - mod = new MyModule - mod - } - val expected = Seq( - "clock" -> mod.clock, - "reset" -> mod.reset, - "io" -> mod.io, - "io_out" -> mod.io.out, - "io_out_0" -> mod.io.out(0), - "io_out_1" -> mod.io.out(1), - "io_in" -> mod.io.in, - "extra" -> mod.extra - ) - (DataMirror.fullModulePorts(mod) should contain).theSameElementsInOrderAs(expected) - } - - property("A desiredName parameterized by a submodule should work") { - ChiselStage.elaborate(new ModuleWrapper(new ModuleWire)).name should be("ModuleWireWrapper") - } - property("A name generating a null pointer exception should provide a good error message") { - (the[ChiselException] thrownBy extractCause[ChiselException]( - ChiselStage.elaborate(new NullModuleWrapper) - )).getMessage should include("desiredName of chiselTests.NullModuleWrapper is null") - } - property("The name of a module in a function should be sane") { - def foo = { - class Foo1 extends RawModule { - assert(name == "Foo1") - } - new Foo1 - } - ChiselStage.elaborate(foo) - } - property("The name of an anonymous module should include '_Anon'") { - trait Foo { this: RawModule => - assert(name.contains("_Anon")) - } - ChiselStage.elaborate(new RawModule with Foo) - } - - property("getVerilogString(new PlusOne() should produce a valid Verilog string") { - val s = getVerilogString(new PlusOne()) - assert(s.contains("assign io_out = io_in + 32'h1")) - assert(s.contains("RANDOMIZE_REG_INIT")) - } - - property("getVerilogString(new PlusOne() should produce a valid Verilog string with arguments") { - val s = getVerilogString(new PlusOne(), Array("--emission-options=disableRegisterRandomization")) - assert(s.contains("assign io_out = io_in + 32'h1")) - assert(!s.contains("RANDOMIZE_REG_INIT")) - } - - property("emitVerilog((new PlusOne()..) shall produce a valid Verilog file in a subfolder") { - emitVerilog(new PlusOne(), Array("--target-dir", "generated")) - val s = Source.fromFile("generated/PlusOne.v").mkString("") - assert(s.contains("assign io_out = io_in + 32'h1")) - } -} diff --git a/src/test/scala/chiselTests/ModuleExplicitResetSpec.scala b/src/test/scala/chiselTests/ModuleExplicitResetSpec.scala deleted file mode 100644 index 1a55fb3f..00000000 --- a/src/test/scala/chiselTests/ModuleExplicitResetSpec.scala +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3.stage.ChiselStage - -class ModuleExplicitResetSpec extends ChiselFlatSpec { - - "A Module with an explicit reset in compatibility mode" should "elaborate" in { - import Chisel._ - val myReset = true.B - class ModuleExplicitReset(reset: Bool) extends Module(_reset = reset) { - val io = new Bundle { - val done = Bool(OUTPUT) - } - - io.done := false.B - } - - ChiselStage.elaborate { - new ModuleExplicitReset(myReset) - } - } -} diff --git a/src/test/scala/chiselTests/MulLookup.scala b/src/test/scala/chiselTests/MulLookup.scala deleted file mode 100644 index 0f67ea34..00000000 --- a/src/test/scala/chiselTests/MulLookup.scala +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.testers.BasicTester - -class MulLookup(val w: Int) extends Module { - val io = IO(new Bundle { - val x = Input(UInt(w.W)) - val y = Input(UInt(w.W)) - val z = Output(UInt((2 * w).W)) - }) - val tbl = VecInit( - for { - i <- 0 until 1 << w - j <- 0 until 1 << w - } yield (i * j).asUInt((2 * w).W) - ) - io.z := tbl(((io.x << w) | io.y)) -} - -class MulLookupTester(w: Int, x: Int, y: Int) extends BasicTester { - val dut = Module(new MulLookup(w)) - dut.io.x := x.asUInt - dut.io.y := y.asUInt - assert(dut.io.z === (x * y).asUInt) - stop() -} - -class MulLookupSpec extends ChiselPropSpec { - - property("Mul lookup table should return the correct result") { - forAll(smallPosInts, smallPosInts) { (x: Int, y: Int) => - assertTesterPasses { new MulLookupTester(3, x, y) } - } - } -} diff --git a/src/test/scala/chiselTests/MultiAssign.scala b/src/test/scala/chiselTests/MultiAssign.scala deleted file mode 100644 index 4cb51feb..00000000 --- a/src/test/scala/chiselTests/MultiAssign.scala +++ /dev/null @@ -1,82 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.testers.BasicTester -import chisel3.stage.ChiselStage -import chisel3.util._ - -class LastAssignTester() extends BasicTester { - val countOnClockCycles = true.B - val (cnt, wrap) = Counter(countOnClockCycles, 2) - - val test = Wire(UInt(4.W)) - assert(test === 7.U) // allow read references before assign references - - test := 13.U - assert(test === 7.U) // output value should be position-independent - - test := 7.U - assert(test === 7.U) // this obviously should work - - when(cnt === 1.U) { - stop() - } -} - -class MultiAssignSpec extends ChiselFlatSpec { - "The last assignment" should "be used when multiple assignments happen" in { - assertTesterPasses { new LastAssignTester } - } -} - -class IllegalAssignSpec extends ChiselFlatSpec with Utils { - "Reassignments to literals" should "be disallowed" in { - intercept[chisel3.internal.ChiselException] { - extractCause[ChiselException] { - ChiselStage.elaborate { - new BasicTester { - 15.U := 7.U - } - } - } - } - } - - "Reassignments to ops" should "be disallowed" in { - intercept[chisel3.internal.ChiselException] { - extractCause[ChiselException] { - ChiselStage.elaborate { - new BasicTester { - (15.U + 1.U) := 7.U - } - } - } - } - } - - "Reassignments to bit slices" should "be disallowed" in { - intercept[chisel3.internal.ChiselException] { - extractCause[ChiselException] { - ChiselStage.elaborate { - new BasicTester { - (15.U)(1, 0) := 7.U - } - } - } - } - } - - "Bulk-connecting two read-only nodes" should "be disallowed" in { - intercept[chisel3.internal.ChiselException] { - extractCause[ChiselException] { - ChiselStage.elaborate { - new BasicTester { - (15.U + 1.U) <> 7.U - } - } - } - } - } -} diff --git a/src/test/scala/chiselTests/MultiClockSpec.scala b/src/test/scala/chiselTests/MultiClockSpec.scala deleted file mode 100644 index 29ec6509..00000000 --- a/src/test/scala/chiselTests/MultiClockSpec.scala +++ /dev/null @@ -1,290 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.util.Counter -import chisel3.testers.{BasicTester, TesterDriver} -import chisel3.stage.ChiselStage - -/** Multi-clock test of a Reg using a different clock via withClock */ -class ClockDividerTest extends BasicTester { - val cDiv = RegInit(true.B) // start with falling edge to simplify clock relationship assert - cDiv := !cDiv - val clock2 = cDiv.asClock - - val reg1 = RegInit(0.U(8.W)) - reg1 := reg1 + 1.U - val reg2 = withClock(clock2) { RegInit(0.U(8.W)) } - reg2 := reg2 + 1.U - - when(reg1 < 10.U) { - assert(reg2 === reg1 / 2.U) // 1:2 clock relationship - } - - when(reg1 === 10.U) { - stop() - } -} - -class MultiClockSubModuleTest extends BasicTester { - class SubModule extends Module { - val io = IO(new Bundle { - val out = Output(UInt()) - }) - val (cycle, _) = Counter(true.B, 10) - io.out := cycle - } - - val (cycle, done) = Counter(true.B, 10) - val cDiv = RegInit(true.B) // start with falling edge to simplify clock relationship assert - cDiv := !cDiv - - val otherClock = cDiv.asClock - val otherReset = cycle < 3.U - - val inst = withClockAndReset(otherClock, otherReset) { Module(new SubModule) } - - when(done) { - // The counter in inst should come out of reset later and increment at half speed - assert(inst.io.out === 3.U) - stop() - } -} - -/** Test withReset changing the reset of a Reg */ -class WithResetTest extends BasicTester { - val reset2 = WireDefault(false.B) - val reg = withReset(reset2 || reset.asBool) { RegInit(0.U(8.W)) } - reg := reg + 1.U - - val (cycle, done) = Counter(true.B, 10) - when(cycle < 7.U) { - assert(reg === cycle) - }.elsewhen(cycle === 7.U) { - reset2 := true.B - }.elsewhen(cycle === 8.U) { - assert(reg === 0.U) - } - when(done) { stop() } -} - -/** Test Mem ports with different clocks */ -class MultiClockMemTest extends BasicTester { - val cDiv = RegInit(true.B) - cDiv := !cDiv - val clock2 = cDiv.asClock - - val mem = Mem(8, UInt(32.W)) - - val (cycle, done) = Counter(true.B, 20) - - // Write port 1 walks through writing 123 - val waddr = RegInit(0.U(3.W)) - waddr := waddr + 1.U - when(cycle < 8.U) { - mem(waddr) := 123.U - } - - val raddr = waddr - 1.U - val rdata = mem(raddr) - - // Check each write from write port 1 - when(cycle > 0.U && cycle < 9.U) { - assert(rdata === 123.U) - } - - // Write port 2 walks through writing 456 on 2nd time through - withClock(clock2) { - when(cycle >= 8.U && cycle < 16.U) { - mem(waddr) := 456.U // write 456 to different address - } - } - - // Check that every even address gets 456 - when(cycle > 8.U && cycle < 17.U) { - when(raddr % 2.U === 0.U) { - assert(rdata === 456.U) - }.otherwise { - assert(rdata === 123.U) - } - } - - when(done) { stop() } -} - -class MultiClockSpec extends ChiselFlatSpec with Utils { - - "withClock" should "scope the clock of registers" in { - assertTesterPasses(new ClockDividerTest) - } - - it should "scope ports of memories" in { - assertTesterPasses(new MultiClockMemTest, annotations = TesterDriver.verilatorOnly) - } - - it should "return like a normal Scala block" in { - ChiselStage.elaborate(new BasicTester { - assert(withClock(this.clock) { 5 } == 5) - }) - } - - "Differing clocks at memory and port instantiation" should "warn" in { - class modMemDifferingClock extends Module { - val myClock = IO(Input(Clock())) - val mem = withClock(myClock) { Mem(4, UInt(8.W)) } - val port0 = mem(0.U) - } - val (logMemDifferingClock, _) = grabLog(ChiselStage.elaborate(new modMemDifferingClock)) - logMemDifferingClock should include("memory is different") - - class modSyncReadMemDifferingClock extends Module { - val myClock = IO(Input(Clock())) - val mem = withClock(myClock) { SyncReadMem(4, UInt(8.W)) } - val port0 = mem(0.U) - } - val (logSyncReadMemDifferingClock, _) = grabLog(ChiselStage.elaborate(new modSyncReadMemDifferingClock)) - logSyncReadMemDifferingClock should include("memory is different") - } - - "Differing clocks at memory and write accessor instantiation" should "warn" in { - class modMemWriteDifferingClock extends Module { - val myClock = IO(Input(Clock())) - val mem = withClock(myClock) { Mem(4, UInt(8.W)) } - mem(1.U) := 1.U - } - val (logMemWriteDifferingClock, _) = grabLog(ChiselStage.elaborate(new modMemWriteDifferingClock)) - logMemWriteDifferingClock should include("memory is different") - - class modSyncReadMemWriteDifferingClock extends Module { - val myClock = IO(Input(Clock())) - val mem = withClock(myClock) { SyncReadMem(4, UInt(8.W)) } - mem.write(1.U, 1.U) - } - val (logSyncReadMemWriteDifferingClock, _) = grabLog(ChiselStage.elaborate(new modSyncReadMemWriteDifferingClock)) - logSyncReadMemWriteDifferingClock should include("memory is different") - } - - "Differing clocks at memory and read accessor instantiation" should "warn" in { - class modSyncReadMemReadDifferingClock extends Module { - val myClock = IO(Input(Clock())) - val mem = withClock(myClock) { SyncReadMem(4, UInt(8.W)) } - val readVal = mem.read(0.U) - } - val (logSyncReadMemReadDifferingClock, _) = grabLog(ChiselStage.elaborate(new modSyncReadMemReadDifferingClock)) - logSyncReadMemReadDifferingClock should include("memory is different") - } - - "Passing clock parameter to memory port instantiation" should "not warn" in { - class modMemPortClock extends Module { - val myClock = IO(Input(Clock())) - val mem = Mem(4, UInt(8.W)) - val port0 = mem(0.U, myClock) - } - val (logMemPortClock, _) = grabLog(ChiselStage.elaborate(new modMemPortClock)) - (logMemPortClock should not).include("memory is different") - - class modSyncReadMemPortClock extends Module { - val myClock = IO(Input(Clock())) - val mem = SyncReadMem(4, UInt(8.W)) - val port0 = mem(0.U, myClock) - } - val (logSyncReadMemPortClock, _) = grabLog(ChiselStage.elaborate(new modSyncReadMemPortClock)) - (logSyncReadMemPortClock should not).include("memory is different") - } - - "Passing clock parameter to memory write accessor" should "not warn" in { - class modMemWriteClock extends Module { - val myClock = IO(Input(Clock())) - val mem = Mem(4, UInt(8.W)) - mem.write(0.U, 0.U, myClock) - } - val (logMemWriteClock, _) = grabLog(ChiselStage.elaborate(new modMemWriteClock)) - (logMemWriteClock should not).include("memory is different") - - class modSyncReadMemWriteClock extends Module { - val myClock = IO(Input(Clock())) - val mem = SyncReadMem(4, UInt(8.W)) - mem.write(0.U, 0.U, myClock) - } - val (logSyncReadMemWriteClock, _) = grabLog(ChiselStage.elaborate(new modSyncReadMemWriteClock)) - (logSyncReadMemWriteClock should not).include("memory is different") - } - - "Passing clock parameter to memory read accessor" should "not warn" in { - class modMemReadClock extends Module { - val myClock = IO(Input(Clock())) - val mem = Mem(4, UInt(8.W)) - val readVal = mem.read(0.U, myClock) - } - val (logMemReadClock, _) = grabLog(ChiselStage.elaborate(new modMemReadClock)) - (logMemReadClock should not).include("memory is different") - - class modSyncReadMemReadClock extends Module { - val myClock = IO(Input(Clock())) - val mem = SyncReadMem(4, UInt(8.W)) - val readVal = mem.read(0.U, myClock) - } - val (logSyncReadMemReadClock, _) = grabLog(ChiselStage.elaborate(new modSyncReadMemReadClock)) - (logSyncReadMemReadClock should not).include("memory is different") - } - - "withReset" should "scope the reset of registers" in { - assertTesterPasses(new WithResetTest) - } - - it should "scope the clock and reset of Modules" in { - assertTesterPasses(new MultiClockSubModuleTest) - } - - it should "return like a normal Scala block" in { - ChiselStage.elaborate(new BasicTester { - assert(withReset(this.reset) { 5 } == 5) - }) - } - it should "support literal Bools" in { - assertTesterPasses(new BasicTester { - val reg = withReset(true.B) { - RegInit(6.U) - } - reg := reg - 1.U - // The reg is always in reset so will never decrement - chisel3.assert(reg === 6.U) - val (_, done) = Counter(true.B, 4) - when(done) { stop() } - }) - } - - "withClockAndReset" should "return like a normal Scala block" in { - ChiselStage.elaborate(new BasicTester { - assert(withClockAndReset(this.clock, this.reset) { 5 } == 5) - }) - } - - it should "scope the clocks and resets of asserts" in { - // Check that assert can fire - assertTesterFails(new BasicTester { - withClockAndReset(clock, reset) { - chisel3.assert(0.U === 1.U) - } - val (_, done) = Counter(true.B, 2) - when(done) { stop() } - }) - // Check that reset will block - assertTesterPasses(new BasicTester { - withClockAndReset(clock, true.B) { - chisel3.assert(0.U === 1.U) - } - val (_, done) = Counter(true.B, 2) - when(done) { stop() } - }) - // Check that no rising edge will block - assertTesterPasses(new BasicTester { - withClockAndReset(false.B.asClock, reset) { - chisel3.assert(0.U === 1.U) - } - val (_, done) = Counter(true.B, 2) - when(done) { stop() } - }) - } -} diff --git a/src/test/scala/chiselTests/MultiIOModule.scala b/src/test/scala/chiselTests/MultiIOModule.scala deleted file mode 100644 index c65d8fc4..00000000 --- a/src/test/scala/chiselTests/MultiIOModule.scala +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.testers.BasicTester - -class MultiIOPlusOne extends Module { - val in = IO(Input(UInt(32.W))) - val out = IO(Output(UInt(32.W))) - - out := in + 1.asUInt -} - -class MultiIOTester extends BasicTester { - val plusModule = Module(new MultiIOPlusOne) - plusModule.in := 42.U - assert(plusModule.out === 43.U) - stop() -} - -// Demonstrate multiple IOs with inheritance where the IO is assigned to internally -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 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 Module with LiteralOutputTrait with MultiIOTrait { - val topModuleIO = IO(Input(UInt(32.W))) - myTraitIO := topModuleIO -} - -class ComposedMultiIOTester extends BasicTester { - val composedModule = Module(new ComposedMultiIOModule) - composedModule.topModuleIO := 42.U - assert(composedModule.myTraitIO === 42.U) - assert(composedModule.myLiteralIO === 2.U) - stop() -} - -class MultiIOSpec extends ChiselFlatSpec { - "Multiple IOs in MultiIOModule" should "work" in { - assertTesterPasses({ new MultiIOTester }) - } - "Composed MultiIO Modules" should "work" in { - assertTesterPasses({ new ComposedMultiIOTester }) - } -} diff --git a/src/test/scala/chiselTests/MuxSpec.scala b/src/test/scala/chiselTests/MuxSpec.scala deleted file mode 100644 index 03505f2d..00000000 --- a/src/test/scala/chiselTests/MuxSpec.scala +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.util.{log2Ceil, MuxLookup} -import chisel3.testers.BasicTester - -class MuxTester extends BasicTester { - assert(Mux(0.B, 1.U, 2.U) === 2.U) - assert(Mux(1.B, 1.U, 2.U) === 1.U) - val dontCareMux1 = Wire(UInt()) - dontCareMux1 := Mux(0.B, DontCare, 4.U) // note: Mux output of type Element - assert(dontCareMux1 === 4.U) - - val dontCareMux2 = Wire(UInt()) - dontCareMux2 := Mux(1.B, 3.U, DontCare) // note: Mux output of type Element - assert(dontCareMux2 === 3.U) - - Mux(0.B, 3.U, DontCare) // just to make sure nothing crashes, any result is valid - stop() -} - -class MuxSpec extends ChiselFlatSpec { - "Mux" should "pass basic checks" in { - assertTesterPasses { new MuxTester } - } -} - -class MuxLookupWrapper(keyWidth: Int, default: Int, mapping: () => Seq[(UInt, UInt)]) extends RawModule { - val outputWidth = log2Ceil(default).max(keyWidth) // make room for default value - val key = IO(Input(UInt(keyWidth.W))) - val output = IO(Output(UInt(outputWidth.W))) - output := MuxLookup(key, default.U, mapping()) -} - -class MuxLookupExhaustiveSpec extends ChiselPropSpec { - val keyWidth = 2 - val default = 9 // must be less than 10 to avoid hex/decimal mismatches - val firrtlLit = s"""UInt<4>("h$default")""" - - // Assumes there are no literals with 'UInt<4>("h09")' in the output FIRRTL - // Assumes no binary recoding in output - - val incomplete = () => Seq(0.U -> 1.U, 1.U -> 2.U, 2.U -> 3.U) - property("The default value should not be optimized away for an incomplete MuxLookup") { - ChiselStage.emitChirrtl(new MuxLookupWrapper(keyWidth, default, incomplete)) should include(firrtlLit) - } - - val exhaustive = () => (3.U -> 0.U) +: incomplete() - property("The default value should be optimized away for an exhaustive MuxLookup") { - (ChiselStage.emitChirrtl(new MuxLookupWrapper(keyWidth, default, exhaustive)) should not).include(firrtlLit) - } - - val overlap = () => (4096.U -> 0.U) +: incomplete() - property("The default value should not be optimized away for a MuxLookup with 2^{keyWidth} non-distinct mappings") { - ChiselStage.emitChirrtl(new MuxLookupWrapper(keyWidth, default, overlap)) should include(firrtlLit) - } - - val nonLiteral = () => { val foo = Wire(UInt()); (foo -> 1.U) +: incomplete() } - property("The default value should not be optimized away for a MuxLookup with a non-literal") { - ChiselStage.emitChirrtl(new MuxLookupWrapper(keyWidth, default, nonLiteral)) should include(firrtlLit) - } - - val nonLiteralStillFull = () => { val foo = Wire(UInt()); (foo -> 1.U) +: exhaustive() } - property("The default value should be optimized away for a MuxLookup with a non-literal that is still full") { - (ChiselStage.emitChirrtl(new MuxLookupWrapper(keyWidth, default, nonLiteralStillFull)) should not) - .include(firrtlLit) - } - -} diff --git a/src/test/scala/chiselTests/NamingAnnotationTest.scala b/src/test/scala/chiselTests/NamingAnnotationTest.scala deleted file mode 100644 index a3f39c51..00000000 --- a/src/test/scala/chiselTests/NamingAnnotationTest.scala +++ /dev/null @@ -1,267 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.experimental.chiselName -import chisel3.experimental.AffectsChiselPrefix -import chisel3.internal.InstanceId -import chisel3.stage.ChiselStage - -import scala.collection.mutable.ListBuffer - -trait NamedModuleTester extends Module with AffectsChiselPrefix { - val expectedNameMap = ListBuffer[(InstanceId, String)]() - val expectedModuleNameMap = ListBuffer[(Module, String)]() - - /** Expects some name for a node that is propagated to FIRRTL. - * The node is returned allowing this to be called inline. - */ - def expectName[T <: InstanceId](node: T, fullName: String): T = { - expectedNameMap += ((node, fullName)) - node - } - - /** Expects some name for a module declaration that is propagated to FIRRTL. - * The node is returned allowing this to be called inline. - */ - def expectModuleName[T <: Module](node: T, fullName: String): T = { - expectedModuleNameMap += ((node, fullName)) - node - } - - /** After this module has been elaborated, returns a list of (node, expected name, actual name) - * that did not match expectations. - * Returns an empty list if everything was fine. - */ - def getNameFailures(): List[(InstanceId, String, String)] = { - val failures = ListBuffer[(InstanceId, String, String)]() - for ((ref, expectedName) <- expectedNameMap) { - if (ref.instanceName != expectedName) { - failures += ((ref, expectedName, ref.instanceName)) - } - } - for ((mod, expectedModuleName) <- expectedModuleNameMap) { - if (mod.name != expectedModuleName) { - failures += ((mod, expectedModuleName, mod.name)) - } - } - failures.toList - } -} -class OuterNamedNonModule extends AffectsChiselPrefix { - val value = Wire(Bool()) -} - -class NonModule extends AffectsChiselPrefix { - val value = Wire(Bool()) - class InnerNamedNonModule extends AffectsChiselPrefix { - val value = Wire(Bool()) - } - val inner = new InnerNamedNonModule - val outer = new OuterNamedNonModule -} - -class NamedModule extends NamedModuleTester { - def FunctionMockupInner(): UInt = { - val my2A = 1.U - val my2B = expectName(my2A +& 2.U, "test_myNested_my2B") - val my2C = my2B +& 3.U // should get named at enclosing scope - my2C - } - - def FunctionMockup(): UInt = { - val myNested = expectName(FunctionMockupInner(), "test_myNested") - val myA = expectName(1.U + myNested, "test_myA") - val myB = expectName(myA +& 2.U, "test_myB") - val myC = expectName(myB +& 3.U, "test_myC") - - val myD = Seq(myC +& 1.U, myC +& 2.U) - for ((d, i) <- myD.zipWithIndex) - expectName(d, s"test_myD_$i") - - myC +& 4.U // named at enclosing scope - } - - // chiselName "implicitly" applied - def ImplicitlyNamed(): UInt = { - val implicitA = expectName(1.U + 2.U, "test3_implicitA") - val implicitB = expectName(implicitA + 3.U, "test3_implicitB") - implicitB + 2.U // named at enclosing scope - } - - // Ensure this applies a partial name if there is no return value - def NoReturnFunction() { - val noreturn = expectName(1.U + 2.U, "noreturn") - } - - val test = expectName(FunctionMockup(), "test") - val test2 = expectName(test +& 2.U, "test2") - val test3 = expectName(ImplicitlyNamed(), "test3") - - val test4 = new NonModule - expectName(test4.value, "test4_value") - expectName(test4.inner.value, "test4_inner_value") - expectName(test4.outer.value, "test4_outer_value") - - // Test that contents of for loops are named - for (i <- 0 until 1) { - val forInner = expectName(test3 + i.U, "forInner") - } - - // Test that contents of anonymous functions are named - Seq((0, "anonInner"), (1, "anonInner_1"), (2, "anonInner_2")).foreach { - case (in, name) => - val anonInner = expectName(test3 + in.U, name) - } - - NoReturnFunction() -} - -class NameCollisionModule extends NamedModuleTester { - def repeatedCalls(name: String): UInt = { - val test = expectName(1.U + 3.U, s"${name}_test") // should disambiguate by invocation order - test + 2.U - } - - // chiselName applied by default to this - def innerNamedFunction() { - // ... but not this inner function - def innerUnnamedFunction() { - val a = repeatedCalls("a") - val b = repeatedCalls("b") - } - - innerUnnamedFunction() - } - - val test = expectName(1.U + 2.U, "test") - innerNamedFunction() -} - -/** Ensure no crash happens if a named function is enclosed in a non-named module - */ -class NonNamedModule extends NamedModuleTester { - @chiselName - def NamedFunction(): UInt = { - val myVal = 1.U + 2.U - myVal - } - - val test = NamedFunction() -} - -/** Ensure no crash happens if a named function is enclosed in a non-named function in a named - * module. - */ -object NonNamedHelper { - @chiselName - def NamedFunction(): UInt = { - val myVal = 1.U + 2.U - myVal - } - - def NonNamedFunction(): UInt = { - val myVal = NamedFunction() - myVal - } - - @chiselName - def NonBuilderFunction(): Int = { - 1 + 1 - } -} - -@chiselName -class NonNamedFunction extends NamedModuleTester { - val test = NonNamedHelper.NamedFunction() -} - -/** Ensure broken links in the chain are simply dropped - */ -@chiselName -class PartialNamedModule extends NamedModuleTester { - // Create an inner function that is the extent of the implicit naming - def innerNamedFunction(): UInt = { - def innerUnnamedFunction(): UInt = { - @chiselName - def disconnectedNamedFunction(): UInt = { - val a = expectName(1.U + 2.U, "test_a") - val b = expectName(a + 2.U, "test_b") - b - } - disconnectedNamedFunction() - } - innerUnnamedFunction() + 1.U - } - - val test = innerNamedFunction() -} - -@chiselName -class NoChiselNamePrefixTester extends NamedModuleTester { - @chiselName - class NoChiselNamePrefixClass extends chisel3.experimental.NoChiselNamePrefix { - val a = expectName(1.U +& 2.U, "a") - } - val inst = new NoChiselNamePrefixClass - class NormalClass { - val b = 1.U +& 2.U - } - val foo = new NormalClass with AffectsChiselPrefix - expectName(foo.b, "foo_b") - val bar = new NormalClass with chisel3.experimental.NoChiselNamePrefix - expectName(bar.b, "b") - - // Check that we're not matching by name but actual type - trait NoChiselNamePrefix - class FakeNoChiselNamePrefix extends NoChiselNamePrefix with AffectsChiselPrefix { - val c = 1.U +& 2.U - } - val fizz = new FakeNoChiselNamePrefix - expectName(fizz.c, "fizz_c") -} - -/** A simple test that checks the recursive function val naming annotation both compiles and - * generates the expected names. - */ -class NamingAnnotationSpec extends ChiselPropSpec { - property("NamedModule should have function hierarchical names") { - // TODO: clean up test style - var module: NamedModule = null - ChiselStage.elaborate { module = new NamedModule; module } - assert(module.getNameFailures() == Nil) - } - - property("NameCollisionModule should disambiguate collisions") { - // TODO: clean up test style - var module: NameCollisionModule = null - ChiselStage.elaborate { module = new NameCollisionModule; module } - assert(module.getNameFailures() == Nil) - } - - property("PartialNamedModule should have partial names") { - // TODO: clean up test style - var module: PartialNamedModule = null - ChiselStage.elaborate { module = new PartialNamedModule; module } - assert(module.getNameFailures() == Nil) - } - - property("NonNamedModule should elaborate") { - ChiselStage.elaborate { new NonNamedModule } - } - - property("NonNamedFunction should elaborate") { - ChiselStage.elaborate { new NonNamedFunction } - } - - property("NonBuilderFunction should run outside a Builder context") { - NonNamedHelper.NonBuilderFunction() should be(2) - } - - property("NoChiselNamePrefix should prevent prefixing when using @chiselName") { - var module: NoChiselNamePrefixTester = null - ChiselStage.elaborate { module = new NoChiselNamePrefixTester; module } - assert(module.getNameFailures().isEmpty) - } -} diff --git a/src/test/scala/chiselTests/NewAnnotationsSpec.scala b/src/test/scala/chiselTests/NewAnnotationsSpec.scala deleted file mode 100644 index 38e1c1d9..00000000 --- a/src/test/scala/chiselTests/NewAnnotationsSpec.scala +++ /dev/null @@ -1,72 +0,0 @@ -package chiselTests -import chisel3._ -import chisel3.experimental.{annotate, ChiselMultiAnnotation} -import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} -import firrtl.stage.FirrtlCircuitAnnotation -import org.scalatest.freespec.AnyFreeSpec -import org.scalatest.matchers.should.Matchers -import firrtl.transforms.NoDedupAnnotation -import firrtl.transforms.DontTouchAnnotation - -class NewAnnotationsSpec extends AnyFreeSpec with Matchers { - - class MuchUsedModule extends Module { - val io = IO(new Bundle { - val in = Input(UInt(16.W)) - val out = Output(UInt(16.W)) - }) - io.out := io.in +% 1.U - } - - class UsesMuchUsedModule extends Module { - val io = IO(new Bundle { - val in = Input(UInt(16.W)) - val out = Output(UInt(16.W)) - }) - - val mod0 = Module(new MuchUsedModule) - val mod1 = Module(new MuchUsedModule) - val mod2 = Module(new MuchUsedModule) - val mod3 = Module(new MuchUsedModule) - - mod0.io.in := io.in - mod1.io.in := mod0.io.out - mod2.io.in := mod1.io.out - mod3.io.in := mod2.io.out - io.out := mod3.io.out - - // Give two annotations as single element of the seq - ensures previous API works by wrapping into a seq. - annotate(new ChiselMultiAnnotation { def toFirrtl = Seq(new NoDedupAnnotation(mod2.toNamed)) }) - annotate(new ChiselMultiAnnotation { def toFirrtl = Seq(new NoDedupAnnotation(mod3.toNamed)) }) - - // Pass multiple annotations in the same seq - should get emitted out correctly. - annotate(new ChiselMultiAnnotation { - def toFirrtl = - Seq(new DontTouchAnnotation(mod1.io.in.toNamed), new DontTouchAnnotation(mod1.io.out.toNamed)) - }) - } - - val stage = new ChiselStage - "Ensure all annotations continue to be passed / digested correctly with the new API" - { - "NoDedup and DontTouch work as expected" in { - val dutAnnos = stage - .execute( - Array("-X", "low", "--target-dir", "test_run_dir"), - Seq(ChiselGeneratorAnnotation(() => new UsesMuchUsedModule)) - ) - - val dontTouchAnnos = dutAnnos.collect { case DontTouchAnnotation(target) => target.serialize } - val noDedupAnnos = dutAnnos.collect { case NoDedupAnnotation(target) => target.serialize } - require(dontTouchAnnos.size == 2, s"Exactly two DontTouch Annotations expected but got $dontTouchAnnos ") - require(noDedupAnnos.size == 2, s"Exactly two NoDedup Annotations expected but got $noDedupAnnos ") - val dontTouchAnnosCombined = dontTouchAnnos.mkString(",") - val noDedupAnnosCombined = noDedupAnnos.mkString(",") - - noDedupAnnosCombined should include("~UsesMuchUsedModule|MuchUsedModule_2") - noDedupAnnosCombined should include("~UsesMuchUsedModule|MuchUsedModule_3") - dontTouchAnnosCombined should include("~UsesMuchUsedModule|UsesMuchUsedModule/mod1:MuchUsedModule>io_out") - dontTouchAnnosCombined should include("~UsesMuchUsedModule|UsesMuchUsedModule/mod1:MuchUsedModule>io_in") - - } - } -} diff --git a/src/test/scala/chiselTests/OneHotMuxSpec.scala b/src/test/scala/chiselTests/OneHotMuxSpec.scala deleted file mode 100644 index b069b219..00000000 --- a/src/test/scala/chiselTests/OneHotMuxSpec.scala +++ /dev/null @@ -1,318 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.experimental.FixedPoint -import chisel3.internal.ChiselException -import chisel3.testers.BasicTester -import chisel3.util.{Mux1H, UIntToOH} -import org.scalatest._ -import org.scalatest.freespec.AnyFreeSpec -import org.scalatest.matchers.should.Matchers - -class OneHotMuxSpec extends AnyFreeSpec with Matchers with ChiselRunners { - "simple one hot mux with uint should work" in { - assertTesterPasses(new SimpleOneHotTester) - } - "simple one hot mux with sint should work" in { - assertTesterPasses(new SIntOneHotTester) - } - "simple one hot mux with fixed point should work" in { - assertTesterPasses(new FixedPointOneHotTester) - } - "simple one hot mux with all same fixed point should work" in { - assertTesterPasses(new AllSameFixedPointOneHotTester) - } - "simple one hot mux with all same parameterized sint values should work" in { - assertTesterPasses(new ParameterizedOneHotTester) - } - "simple one hot mux with all same parameterized aggregates containing fixed values should work" in { - assertTesterPasses(new ParameterizedAggregateOneHotTester) - } - "simple one hot mux with all aggregates containing inferred width fixed values should NOT work" in { - intercept[ChiselException] { - assertTesterPasses(new InferredWidthAggregateOneHotTester) - } - } - "simple one hot mux with all fixed width bundles but with different bundles should Not work" in { - intercept[IllegalArgumentException] { - assertTesterPasses(new DifferentBundleOneHotTester) - } - } - "UIntToOH with output width greater than 2^(input width)" in { - assertTesterPasses(new UIntToOHTester) - } - "UIntToOH should not accept width of zero (until zero-width wires are fixed" in { - intercept[IllegalArgumentException] { - assertTesterPasses(new BasicTester { - val out = UIntToOH(0.U, 0) - }) - } - } - -} - -class SimpleOneHotTester extends BasicTester { - val out = Wire(UInt()) - out := Mux1H( - Seq( - false.B -> 2.U, - false.B -> 4.U, - true.B -> 8.U, - false.B -> 11.U - ) - ) - - assert(out === 8.U) - - stop() -} - -class SIntOneHotTester extends BasicTester { - val out = Wire(SInt()) - out := Mux1H( - Seq( - false.B -> (-3).S, - true.B -> (-5).S, - false.B -> (-7).S, - false.B -> (-11).S - ) - ) - - assert(out === (-5).S) - - stop() -} - -class FixedPointOneHotTester extends BasicTester { - val out = Wire(FixedPoint(8.W, 4.BP)) - - out := Mux1H( - Seq( - false.B -> (-1.5).F(1.BP), - true.B -> (-2.25).F(2.BP), - false.B -> (-4.125).F(3.BP), - false.B -> (-11.625).F(3.BP) - ) - ) - - assert(out === (-2.25).F(4.BP)) - - stop() -} - -class AllSameFixedPointOneHotTester extends BasicTester { - val out = Wire(FixedPoint(12.W, 3.BP)) - - out := Mux1H( - Seq( - false.B -> (-1.5).F(12.W, 3.BP), - true.B -> (-2.25).F(12.W, 3.BP), - false.B -> (-4.125).F(12.W, 3.BP), - false.B -> (-11.625).F(12.W, 3.BP) - ) - ) - - assert(out === (-2.25).F(14.W, 4.BP)) - - stop() -} - -class ParameterizedOneHotTester extends BasicTester { - val values: Seq[Int] = Seq(-3, -5, -7, -11) - for ((v, i) <- values.zipWithIndex) { - val dut = Module(new ParameterizedOneHot(values.map(_.S), SInt(8.W))) - dut.io.selectors := (1 << i).U(4.W).asBools - - assert(dut.io.out.asUInt() === v.S(8.W).asUInt()) - } - - stop() -} - -class Agg1 extends Bundle { - val v = Vec(2, FixedPoint(8.W, 4.BP)) - val a = new Bundle { - val f1 = FixedPoint(7.W, 3.BP) - val f2 = FixedPoint(9.W, 5.BP) - } -} - -object Agg1 extends HasMakeLit[Agg1] { - def makeLit(n: Int): Agg1 = { - val x = n.toDouble / 4.0 - val (d: Double, e: Double, f: Double, g: Double) = (x, x * 2.0, x * 3.0, x * 4.0) - - val w = Wire(new Agg1) - w.v(0) := d.F(4.BP) - w.v(1) := e.F(4.BP) - w.a.f1 := f.F(3.BP) - w.a.f2 := g.F(5.BP) - w - } -} -class Agg2 extends Bundle { - val v = Vec(2, FixedPoint(8.W, 4.BP)) - val a = new Bundle { - val f1 = FixedPoint(7.W, 3.BP) - val f2 = FixedPoint(9.W, 5.BP) - } -} - -object Agg2 extends HasMakeLit[Agg2] { - def makeLit(n: Int): Agg2 = { - val x = n.toDouble / 4.0 - val (d: Double, e: Double, f: Double, g: Double) = (x, x * 2.0, x * 3.0, x * 4.0) - - val w = Wire(new Agg2) - w.v(0) := d.F(4.BP) - w.v(1) := e.F(4.BP) - w.a.f1 := f.F(3.BP) - w.a.f2 := g.F(5.BP) - w - } -} - -class ParameterizedAggregateOneHotTester extends BasicTester { - val values = (0 until 4).map { n => Agg1.makeLit(n) } - for ((v, i) <- values.zipWithIndex) { - val dut = Module(new ParameterizedAggregateOneHot(Agg1, new Agg1)) - dut.io.selectors := (1 << i).U(4.W).asBools - - assert(dut.io.out.asUInt() === values(i).asUInt()) - } - - stop() -} - -trait HasMakeLit[T] { - def makeLit(n: Int): T -} - -class ParameterizedOneHot[T <: Data](values: Seq[T], outGen: T) extends Module { - val io = IO(new Bundle { - val selectors = Input(Vec(4, Bool())) - val out = Output(outGen) - }) - - val terms = io.selectors.zip(values) - io.out := Mux1H(terms) -} - -class ParameterizedAggregateOneHot[T <: Data](valGen: HasMakeLit[T], outGen: T) extends Module { - val io = IO(new Bundle { - val selectors = Input(Vec(4, Bool())) - val out = Output(outGen) - }) - - val values = (0 until 4).map { n => valGen.makeLit(n) } - val terms = io.selectors.zip(values) - io.out := Mux1H(terms) -} - -class Bundle1 extends Bundle { - val a = FixedPoint() - val b = new Bundle { - val c = FixedPoint() - } -} - -class InferredWidthAggregateOneHotTester extends BasicTester { - val b0 = Wire(new Bundle1) - b0.a := -0.25.F(2.BP) - b0.b.c := -0.125.F(3.BP) - - val b1 = Wire(new Bundle1) - b1.a := -0.0625.F(3.BP) - b1.b.c := -0.03125.F(4.BP) - - val b2 = Wire(new Bundle1) - b2.a := -0.015625.F(5.BP) - b2.b.c := -0.0078125.F(6.BP) - - val b3 = Wire(new Bundle1) - b3.a := -0.0078125.F(7.BP) - b3.b.c := -0.00390625.F(8.BP) - - val o1 = Mux1H( - Seq( - false.B -> b0, - false.B -> b1, - true.B -> b2, - false.B -> b3 - ) - ) - - assert(o1.a === -0.015625.F(5.BP)) - assert(o1.b.c === -0.0078125.F(6.BP)) - - val o2 = Mux1H( - Seq( - false.B -> b0, - true.B -> b1, - false.B -> b2, - false.B -> b3 - ) - ) - - assert(o2.a === -0.0625.F(3.BP)) - assert(o2.b.c === -0.03125.F(4.BP)) - - stop() -} - -class Bundle2 extends Bundle { - val a = FixedPoint(10.W, 4.BP) - val b = new Bundle { - val c = FixedPoint(10.W, 4.BP) - } -} - -class Bundle3 extends Bundle { - val a = FixedPoint(10.W, 4.BP) - val b = new Bundle { - val c = FixedPoint(10.W, 4.BP) - } -} - -class DifferentBundleOneHotTester extends BasicTester { - val b0 = Wire(new Bundle2) - b0.a := -0.25.F(2.BP) - b0.b.c := -0.125.F(3.BP) - - val b1 = Wire(new Bundle2) - b1.a := -0.0625.F(3.BP) - b1.b.c := -0.03125.F(4.BP) - - val b2 = Wire(new Bundle3) - b2.a := -0.015625.F(5.BP) - b2.b.c := -0.0078125.F(6.BP) - - val b3 = Wire(new Bundle3) - b3.a := -0.0078125.F(7.BP) - b3.b.c := -0.00390625.F(8.BP) - - val o1 = Mux1H( - Seq( - false.B -> b0, - false.B -> b1, - true.B -> b2, - false.B -> b3 - ) - ) - - stop() -} - -class UIntToOHTester extends BasicTester { - val out = UIntToOH(1.U, 3) - require(out.getWidth == 3) - assert(out === 2.U) - - val out2 = UIntToOH(0.U, 1) - require(out2.getWidth == 1) - assert(out2 === 1.U) - - stop() -} diff --git a/src/test/scala/chiselTests/OptionBundle.scala b/src/test/scala/chiselTests/OptionBundle.scala deleted file mode 100644 index 628e117d..00000000 --- a/src/test/scala/chiselTests/OptionBundle.scala +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.testers.BasicTester - -class OptionBundle(val hasIn: Boolean) extends Bundle { - val in = if (hasIn) { - Some(Input(Bool())) - } else { - None - } - val out = Output(Bool()) -} - -class OptionBundleModule(val hasIn: Boolean) extends Module { - val io = IO(new OptionBundle(hasIn)) - if (hasIn) { - io.out := io.in.get - } else { - io.out := false.B - } -} - -class SomeOptionBundleTester(expected: Boolean) extends BasicTester { - val mod = Module(new OptionBundleModule(true)) - mod.io.in.get := expected.asBool - assert(mod.io.out === expected.asBool) - stop() -} - -class NoneOptionBundleTester() extends BasicTester { - val mod = Module(new OptionBundleModule(false)) - assert(mod.io.out === false.B) - stop() -} - -class InvalidOptionBundleTester() extends BasicTester { - val mod = Module(new OptionBundleModule(false)) - mod.io.in.get := true.B - assert(false.B) - stop() -} - -class OptionBundleSpec extends ChiselFlatSpec with Utils { - "A Bundle with an Option field" should "work properly if the Option field is not None" in { - assertTesterPasses { new SomeOptionBundleTester(true) } - assertTesterPasses { new SomeOptionBundleTester(false) } - } - - "A Bundle with an Option field" should "compile if the Option field is None" in { - assertTesterPasses { new NoneOptionBundleTester() } - } - - "A Bundle with an Option field" should "assert out accessing a None Option field" in { - a[Exception] should be thrownBy extractCause[Exception] { - ChiselStage.elaborate { new InvalidOptionBundleTester() } - } - } -} diff --git a/src/test/scala/chiselTests/Padding.scala b/src/test/scala/chiselTests/Padding.scala deleted file mode 100644 index 7950c203..00000000 --- a/src/test/scala/chiselTests/Padding.scala +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage - -class Padder extends Module { - val io = IO(new Bundle { - val a = Input(UInt(4.W)) - val asp = Output(SInt(8.W)) - val aup = Output(UInt(8.W)) - }) - io.asp := io.a.asSInt - io.aup := io.a.asUInt -} - -/* -class PadsTester(c: Pads) extends Tester(c) { - def pads(x: BigInt, s: Int, w: Int) = { - val sign = (x & (1 << (s-1))) - val wmask = (1 << w) - 1 - val bmask = (1 << s) - 1 - if (sign == 0) x else ((~bmask | x) & wmask) - } - for (t <- 0 until 16) { - val test_a = rnd.nextInt(1 << 4) - poke(c.io.a, test_a) - step(1) - expect(c.io.asp, pads(test_a, 4, 8)) - expect(c.io.aup, test_a) - } -} - */ - -class PadderSpec extends ChiselPropSpec { - - property("Padder should elaborate") { - ChiselStage.elaborate { new Padder } - } - - ignore("PadderTester should return the correct result") {} -} diff --git a/src/test/scala/chiselTests/ParameterizedModule.scala b/src/test/scala/chiselTests/ParameterizedModule.scala deleted file mode 100644 index 3ad054f8..00000000 --- a/src/test/scala/chiselTests/ParameterizedModule.scala +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.testers.BasicTester - -class ParameterizedModule(invert: Boolean) extends Module { - val io = IO(new Bundle { - val in = Input(Bool()) - val out = Output(Bool()) - }) - if (invert) { - io.out := !io.in - } else { - io.out := io.in - } -} - -/** A simple test to check Module deduplication doesn't affect correctness (two - * modules with the same name but different contents aren't aliased). Doesn't - * check that deduplication actually happens, though. - */ -class ParameterizedModuleTester() extends BasicTester { - val invert = Module(new ParameterizedModule(true)) - val noninvert = Module(new ParameterizedModule(false)) - - invert.io.in := true.B - noninvert.io.in := true.B - assert(invert.io.out === false.B) - assert(noninvert.io.out === true.B) - - stop() -} - -class ParameterizedModuleSpec extends ChiselFlatSpec { - "Different parameterized modules" should "have different behavior" in { - assertTesterPasses(new ParameterizedModuleTester()) - } -} diff --git a/src/test/scala/chiselTests/PopCount.scala b/src/test/scala/chiselTests/PopCount.scala deleted file mode 100644 index eaea7a2c..00000000 --- a/src/test/scala/chiselTests/PopCount.scala +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.util.PopCount -import chisel3.testers.BasicTester - -class PopCountTester(n: Int) extends BasicTester { - val x = RegInit(0.U(n.W)) - x := x + 1.U - when(RegNext(x === ~0.U(n.W))) { stop() } - - val result = PopCount(x.asBools) - val expected = x.asBools.foldLeft(0.U)(_ +& _) - assert(result === expected) - - require(result.getWidth == BigInt(n).bitLength) -} - -class PopCountSpec extends ChiselPropSpec { - property("Mul lookup table should return the correct result") { - forAll(smallPosInts) { (n: Int) => assertTesterPasses { new PopCountTester(n) } } - } -} diff --git a/src/test/scala/chiselTests/PrintableSpec.scala b/src/test/scala/chiselTests/PrintableSpec.scala deleted file mode 100644 index 8039918d..00000000 --- a/src/test/scala/chiselTests/PrintableSpec.scala +++ /dev/null @@ -1,393 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.experimental.ChiselAnnotation -import chisel3.stage.ChiselStage -import chisel3.testers.BasicTester -import firrtl.annotations.{ReferenceTarget, SingleTargetAnnotation} -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers -import chisel3.util._ -import org.scalactic.source.Position -import java.io.File - -/** Dummy [[printf]] annotation. - * @param target target of component to be annotated - */ -case class PrintfAnnotation(target: ReferenceTarget) extends SingleTargetAnnotation[ReferenceTarget] { - def duplicate(n: ReferenceTarget): PrintfAnnotation = this.copy(target = n) -} - -object PrintfAnnotation { - - /** Create annotation for a given [[printf]]. - * @param c component to be annotated - */ - def annotate(c: VerificationStatement): Unit = { - chisel3.experimental.annotate(new ChiselAnnotation { - def toFirrtl: PrintfAnnotation = PrintfAnnotation(c.toTarget) - }) - } -} - -/* Printable Tests */ -class PrintableSpec extends AnyFlatSpec with Matchers with Utils { - // This regex is brittle, it specifically finds the clock and enable signals followed by commas - private val PrintfRegex = """\s*printf\(\w+, [^,]+,(.*)\).*""".r - private val StringRegex = """([^"]*)"(.*?)"(.*)""".r - private case class Printf(str: String, args: Seq[String]) - private def getPrintfs(firrtl: String): Seq[Printf] = { - def processArgs(str: String): Seq[String] = - str.split(",").map(_.trim).filter(_.nonEmpty) - def processBody(str: String): (String, Seq[String]) = { - str match { - case StringRegex(_, fmt, args) => - (fmt, processArgs(args)) - case _ => fail(s"Regex to process Printf should work on $str!") - } - } - firrtl.split("\n").collect { - case PrintfRegex(matched) => - val (str, args) = processBody(matched) - Printf(str, args) - } - } - - // Generates firrtl, gets Printfs - // Calls fail() if failed match; else calls the partial function which could have its own check - private def generateAndCheck(gen: => RawModule)(check: PartialFunction[Seq[Printf], Unit])(implicit pos: Position) = { - val firrtl = ChiselStage.emitChirrtl(gen) - val printfs = getPrintfs(firrtl) - if (!check.isDefinedAt(printfs)) { - fail() - } else { - check(printfs) - } - } - - behavior.of("Printable & Custom Interpolator") - - it should "pass exact strings through" in { - class MyModule extends BasicTester { - printf(p"An exact string") - } - generateAndCheck(new MyModule) { - case Seq(Printf("An exact string", Seq())) => - } - } - it should "handle Printable and String concatination" in { - class MyModule extends BasicTester { - printf(p"First " + PString("Second ") + "Third") - } - generateAndCheck(new MyModule) { - case Seq(Printf("First Second Third", Seq())) => - } - } - it should "call toString on non-Printable objects" in { - class MyModule extends BasicTester { - val myInt = 1234 - printf(p"myInt = $myInt") - } - generateAndCheck(new MyModule) { - case Seq(Printf("myInt = 1234", Seq())) => - } - } - it should "generate proper printf for simple Decimal printing" in { - class MyModule extends BasicTester { - val myWire = WireDefault(1234.U) - printf(p"myWire = ${Decimal(myWire)}") - } - generateAndCheck(new MyModule) { - case Seq(Printf("myWire = %d", Seq("myWire"))) => - } - } - it should "handle printing literals" in { - class MyModule extends BasicTester { - printf(Decimal(10.U(32.W))) - } - generateAndCheck(new MyModule) { - case Seq(Printf("%d", Seq(lit))) => - assert(lit contains "UInt<32>") - } - } - it should "correctly escape percent" in { - class MyModule extends BasicTester { - printf(p"%") - } - generateAndCheck(new MyModule) { - case Seq(Printf("%%", Seq())) => - } - } - it should "correctly emit tab" in { - class MyModule extends BasicTester { - printf(p"\t") - } - generateAndCheck(new MyModule) { - case Seq(Printf("\\t", Seq())) => - } - } - it should "support names of circuit elements including submodule IO" in { - // Submodule IO is a subtle issue because the Chisel element has a different - // parent module - class MySubModule extends Module { - val io = IO(new Bundle { - val fizz = UInt(32.W) - }) - } - class MyBundle extends Bundle { - val foo = UInt(32.W) - } - class MyModule extends BasicTester { - override def desiredName: String = "MyModule" - val myWire = Wire(new MyBundle) - val myInst = Module(new MySubModule) - printf(p"${Name(myWire.foo)}") - printf(p"${FullName(myWire.foo)}") - printf(p"${FullName(myInst.io.fizz)}") - } - generateAndCheck(new MyModule) { - case Seq(Printf("foo", Seq()), Printf("myWire.foo", Seq()), Printf("myInst.io.fizz", Seq())) => - } - } - it should "handle printing ports of submodules" in { - class MySubModule extends Module { - val io = IO(new Bundle { - val fizz = UInt(32.W) - }) - } - class MyModule extends BasicTester { - val myInst = Module(new MySubModule) - printf(p"${myInst.io.fizz}") - } - generateAndCheck(new MyModule) { - case Seq(Printf("%d", Seq("myInst.io.fizz"))) => - } - } - it should "print UInts and SInts as Decimal by default" in { - class MyModule extends BasicTester { - val myUInt = WireDefault(0.U) - val mySInt = WireDefault(-1.S) - printf(p"$myUInt & $mySInt") - } - generateAndCheck(new MyModule) { - case Seq(Printf("%d & %d", Seq("myUInt", "mySInt"))) => - } - } - it should "print Vecs like Scala Seqs by default" in { - class MyModule extends BasicTester { - val myVec = Wire(Vec(4, UInt(32.W))) - myVec.foreach(_ := 0.U) - printf(p"$myVec") - } - generateAndCheck(new MyModule) { - case Seq(Printf("Vec(%d, %d, %d, %d)", Seq("myVec[0]", "myVec[1]", "myVec[2]", "myVec[3]"))) => - } - } - it should "print Bundles like Scala Maps by default" in { - class MyModule extends BasicTester { - val myBun = Wire(new Bundle { - val foo = UInt(32.W) - val bar = UInt(32.W) - }) - myBun.foo := 0.U - myBun.bar := 0.U - printf(p"$myBun") - } - generateAndCheck(new MyModule) { - case Seq(Printf("AnonymousBundle(foo -> %d, bar -> %d)", Seq("myBun.foo", "myBun.bar"))) => - } - } - it should "get emitted with a name and annotated" in { - - /** Test circuit containing annotated and renamed [[printf]]s. */ - class PrintfAnnotationTest extends Module { - val myBun = Wire(new Bundle { - val foo = UInt(32.W) - val bar = UInt(32.W) - }) - myBun.foo := 0.U - myBun.bar := 0.U - val howdy = printf(p"hello ${myBun}") - PrintfAnnotation.annotate(howdy) - PrintfAnnotation.annotate(printf(p"goodbye $myBun")) - PrintfAnnotation.annotate(printf(p"adieu $myBun").suggestName("farewell")) - } - - // compile circuit - val testDir = new File("test_run_dir", "PrintfAnnotationTest") - (new ChiselStage).emitSystemVerilog( - gen = new PrintfAnnotationTest, - args = Array("-td", testDir.getPath) - ) - - // read in annotation file - val annoFile = new File(testDir, "PrintfAnnotationTest.anno.json") - annoFile should exist - val annoLines = scala.io.Source.fromFile(annoFile).getLines.toList - - // check for expected annotations - exactly(3, annoLines) should include("chiselTests.PrintfAnnotation") - exactly(1, annoLines) should include("~PrintfAnnotationTest|PrintfAnnotationTest>farewell") - exactly(1, annoLines) should include("~PrintfAnnotationTest|PrintfAnnotationTest>printf") - exactly(1, annoLines) should include("~PrintfAnnotationTest|PrintfAnnotationTest>howdy") - - // read in FIRRTL file - val firFile = new File(testDir, "PrintfAnnotationTest.fir") - firFile should exist - val firLines = scala.io.Source.fromFile(firFile).getLines.toList - - // check that verification components have expected names - exactly(1, firLines) should include( - """printf(clock, UInt<1>("h1"), "hello AnonymousBundle(foo -> %d, bar -> %d)", myBun.foo, myBun.bar) : howdy""" - ) - exactly(1, firLines) should include( - """printf(clock, UInt<1>("h1"), "goodbye AnonymousBundle(foo -> %d, bar -> %d)", myBun.foo, myBun.bar) : printf""" - ) - exactly(1, firLines) should include( - """printf(clock, UInt<1>("h1"), "adieu AnonymousBundle(foo -> %d, bar -> %d)", myBun.foo, myBun.bar) : farewell""" - ) - } - - // Unit tests for cf - it should "print regular scala variables with cf format specifier" in { - - class MyModule extends BasicTester { - val f1 = 20.4517 - val i1 = 10 - val str1 = "String!" - printf( - cf"F1 = $f1 D1 = $i1 F1 formatted = $f1%2.2f str1 = $str1%s i1_str = $i1%s i1_hex=$i1%x" - ) - - } - - generateAndCheck(new MyModule) { - case Seq(Printf("F1 = 20.4517 D1 = 10 F1 formatted = 20.45 str1 = String! i1_str = 10 i1_hex=a", Seq())) => - } - } - - it should "print chisel bits with cf format specifier" in { - - class MyBundle extends Bundle { - val foo = UInt(32.W) - val bar = UInt(32.W) - override def toPrintable: Printable = { - cf"Bundle : " + - cf"Foo : $foo%x Bar : $bar%x" - } - } - class MyModule extends BasicTester { - val b1 = 10.U - val w1 = Wire(new MyBundle) - w1.foo := 5.U - w1.bar := 10.U - printf(cf"w1 = $w1") - } - generateAndCheck(new MyModule) { - case Seq(Printf("w1 = Bundle : Foo : %x Bar : %x", Seq("w1.foo", "w1.bar"))) => - } - } - - it should "support names of circuit elements using format specifier including submodule IO with cf format specifier" in { - // Submodule IO is a subtle issue because the Chisel element has a different - // parent module - class MySubModule extends Module { - val io = IO(new Bundle { - val fizz = UInt(32.W) - }) - } - class MyBundle extends Bundle { - val foo = UInt(32.W) - } - class MyModule extends BasicTester { - override def desiredName: String = "MyModule" - val myWire = Wire(new MyBundle) - val myInst = Module(new MySubModule) - printf(cf"${myWire.foo}%n") - printf(cf"${myWire.foo}%N") - printf(cf"${myInst.io.fizz}%N") - } - generateAndCheck(new MyModule) { - case Seq(Printf("foo", Seq()), Printf("myWire.foo", Seq()), Printf("myInst.io.fizz", Seq())) => - } - } - - it should "correctly print strings after modifier" in { - class MyModule extends BasicTester { - val b1 = 10.U - printf(cf"This is here $b1%x!!!! And should print everything else") - } - generateAndCheck(new MyModule) { - case Seq(Printf("This is here %x!!!! And should print everything else", Seq("UInt<4>(\"ha\")"))) => - } - } - - it should "correctly print strings with a lot of literal %% and different format specifiers for Wires" in { - class MyModule extends BasicTester { - val b1 = 10.U - val b2 = 20.U - printf(cf"%% $b1%x%%$b2%b = ${b1 % b2}%d %%%% Tail String") - } - - generateAndCheck(new MyModule) { - case Seq(Printf("%% %x%%%b = %d %%%% Tail String", Seq(lita, litb, _))) => - assert(lita.contains("UInt<4>") && litb.contains("UInt<5>")) - } - } - - it should "not allow unescaped % in the message" in { - class MyModule extends BasicTester { - printf(cf"This should error out for sure because of % - it should be %%") - } - a[java.util.UnknownFormatConversionException] should be thrownBy { - extractCause[java.util.UnknownFormatConversionException] { - ChiselStage.elaborate { new MyModule } - } - } - } - - it should "allow Printables to be expanded and used" in { - class MyModule extends BasicTester { - val w1 = 20.U - val f1 = 30.2 - val i1 = 14 - val pable = cf"w1 = $w1%b f1 = $f1%2.2f" - printf(cf"Trying to expand printable $pable and mix with i1 = $i1%d") - } - generateAndCheck(new MyModule) { - case Seq(Printf("Trying to expand printable w1 = %b f1 = 30.20 and mix with i1 = 14", Seq(lit))) => - assert(lit.contains("UInt<5>")) - } - } - - it should "fail with a single % in the message" in { - class MyModule extends BasicTester { - printf(cf"%") - } - a[java.util.UnknownFormatConversionException] should be thrownBy { - extractCause[java.util.UnknownFormatConversionException] { - ChiselStage.elaborate { new MyModule } - } - } - } - - it should "fail when passing directly to StirngContext.cf a string with literal \\ correctly escaped " in { - a[StringContext.InvalidEscapeException] should be thrownBy { - extractCause[StringContext.InvalidEscapeException] { - val s_seq = Seq("Test with literal \\ correctly escaped") - StringContext(s_seq: _*).cf(Seq(): _*) - } - } - } - - it should "pass correctly escaped \\ when using Printable.pack" in { - class MyModule extends BasicTester { - printf(Printable.pack("\\ \\]")) - } - generateAndCheck(new MyModule) { - case Seq(Printf("\\\\ \\\\]", Seq())) => - } - } -} diff --git a/src/test/scala/chiselTests/Printf.scala b/src/test/scala/chiselTests/Printf.scala deleted file mode 100644 index 6c9f05f0..00000000 --- a/src/test/scala/chiselTests/Printf.scala +++ /dev/null @@ -1,83 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.testers.BasicTester -import chisel3.stage.ChiselStage - -class SinglePrintfTester() extends BasicTester { - val x = 254.U - printf("x=%x", x) - stop() -} - -class ASCIIPrintfTester() extends BasicTester { - printf((0x20 to 0x7e).map(_.toChar).mkString.replace("%", "%%")) - stop() -} - -class MultiPrintfTester() extends BasicTester { - val x = 254.U - val y = 255.U - printf("x=%x y=%x", x, y) - stop() -} - -class ASCIIPrintableTester extends BasicTester { - printf(PString((0x20 to 0x7e).map(_.toChar).mkString(""))) - stop() -} - -class ScopeTesterModule extends Module { - val in = IO(Input(UInt(8.W))) - val out = IO(Output(UInt(8.W))) - out := in - - val w = Wire(UInt(8.W)) - w := 125.U - - val p = cf"$in" - val wp = cf"$w" -} - -class PrintablePrintfScopeTester extends BasicTester { - ChiselStage.elaborate { - new Module { - val mod = Module(new ScopeTesterModule) - printf(mod.p) - } - } - stop() -} - -class PrintablePrintfWireScopeTester extends BasicTester { - ChiselStage.elaborate { - new Module { - val mod = Module(new ScopeTesterModule) - printf(mod.wp) - } - } - stop() -} - -class PrintfSpec extends ChiselFlatSpec { - "A printf with a single argument" should "run" in { - assertTesterPasses { new SinglePrintfTester } - } - "A printf with multiple arguments" should "run" in { - assertTesterPasses { new MultiPrintfTester } - } - "A printf with ASCII characters 1-127" should "run" in { - assertTesterPasses { new ASCIIPrintfTester } - } - "A printf with Printable ASCII characters 1-127" should "run" in { - assertTesterPasses { new ASCIIPrintableTester } - } - "A printf with Printable" should "respect port scopes" in { - assertTesterPasses { new PrintablePrintfScopeTester } - } - "A printf with Printable" should "respect wire scopes" in { - a[ChiselException] should be thrownBy { assertTesterPasses { new PrintablePrintfWireScopeTester } } - } -} diff --git a/src/test/scala/chiselTests/QueueFlushSpec.scala b/src/test/scala/chiselTests/QueueFlushSpec.scala deleted file mode 100644 index d70f9605..00000000 --- a/src/test/scala/chiselTests/QueueFlushSpec.scala +++ /dev/null @@ -1,294 +0,0 @@ -package chiselTests - -import org.scalacheck._ - -import chisel3._ -import chisel3.testers.{BasicTester, TesterDriver} -import chisel3.util._ -import chisel3.util.random.LFSR -import treadle.WriteVcdAnnotation - -/** Test elements can be enqueued and dequeued when flush is tied to false - * - * @param elements The sequence of elements used in the queue - * @param queueDepth The max number of entries in the queue - * @param bitWidth Integer size of the data type used in the queue - * @param tap Integer tap('seed') for the LFSR - * @param useSyncReadMem True uses SyncReadMem instead of Mem as an internal memory element - */ -class ThingsPassThroughFlushQueueTester( - elements: Seq[Int], - queueDepth: Int, - bitWidth: Int, - tap: Int, - useSyncReadMem: Boolean) - extends ThingsPassThroughTester(elements, queueDepth, bitWidth, tap, useSyncReadMem, hasFlush = true) - -/** Generic flush queue tester base class - * - * @param elements The sequence of elements used in the queue - * @param queueDepth The max number of entries in the queue - * @param bitWidth Integer size of the data type used in the queue - * @param tap Integer tap('seed') for the LFSR - * @param useSyncReadMem True uses SyncReadMem instead of Mem as an internal memory element - */ -abstract class FlushQueueTesterBase( - elements: Seq[Int], - queueDepth: Int, - bitWidth: Int, - tap: Int, - useSyncReadMem: Boolean) - extends BasicTester { - val q = Module(new Queue(UInt(bitWidth.W), queueDepth, hasFlush = true)) - val elems = VecInit(elements.map(_.U)) - val inCnt = Counter(elements.length + 1) - val outCnt = RegInit(0.U(log2Ceil(elements.length).W)) - val currQCnt = RegInit(0.U(log2Ceil(5).W)) - - val flush: Bool = WireInit(false.B) - val flushRegister = RegNext(flush, init = false.B) - q.io.flush.get := flush - q.io.enq.valid := (inCnt.value < elements.length.U) - q.io.deq.ready := LFSR(16)(tap) - - q.io.enq.bits := elems(inCnt.value) - when(q.io.enq.fire) { - inCnt.inc() - currQCnt := currQCnt + 1.U //counts how many items have been enqueued - } - when(q.io.deq.fire) { - assert(flushRegister === false.B) //check queue isn't flushed (can't dequeue an empty queue) - } - when(flushRegister) { //Internal signal maybe_full is a register so some signals update on the next cycle - //check that queue gets flushed when queue is full - assert(q.io.count === 0.U) - assert(!q.io.deq.valid, "Expected to not be able to dequeue when flush is asserted the previous cycle") - assert( - q.io.enq.ready, - "Expected enqueue to be ready when flush was asserted the previous cycle because queue should be empty" - ) - } - when(inCnt.value === elements.length.U) { //stop when all entries are enqueued - stop() - } -} - -/** Test queue can flush at random times - * - * @param elements The sequence of elements used in the queue - * @param queueDepth The max number of entries in the queue - * @param bitWidth Integer size of the data type used in the queue - * @param tap Integer tap('seed') for the LFSR - * @param useSyncReadMem True uses SyncReadMem instead of Mem as an internal memory element - */ -class QueueGetsFlushedTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) - extends FlushQueueTesterBase(elements, queueDepth, bitWidth, tap, useSyncReadMem) { - flush := LFSR(16)((tap + 3) % 16) //testing a flush when flush is called randomly - val halfCnt = (queueDepth + 1) / 2 - - when(q.io.deq.fire) { - //ensure that what comes out is what comes in - assert(currQCnt <= queueDepth.U) - assert(elems(outCnt) === q.io.deq.bits) - outCnt := outCnt + 1.U - when(currQCnt > 0.U) { - currQCnt := Mux(q.io.enq.fire, currQCnt, (currQCnt - 1.U)) - } - } - when(flush) { - assert(currQCnt === 0.U || q.io.deq.valid) - outCnt := outCnt + Mux(q.io.enq.fire, (currQCnt + 1.U), currQCnt) - currQCnt := 0.U //resets the number of items currently inside queue - } -} - -/** Test queue can flush when empty - * - * @param elements The sequence of elements used in the queue - * @param queueDepth The max number of entries in the queue - * @param bitWidth Integer size of the data type used in the queue - * @param tap Integer tap('seed') for the LFSR - * @param useSyncReadMem True uses SyncReadMem instead of Mem as an internal memory element - */ -class EmptyFlushEdgecaseTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) - extends FlushQueueTesterBase(elements, queueDepth, bitWidth, tap, useSyncReadMem) { - val cycleCounter = Counter(elements.length + 1) - cycleCounter.inc() //counts every cycle - - //testing a flush when queue is empty - flush := (cycleCounter.value === 0.U && inCnt.value === 0.U) //flushed only before anything is enqueued - q.io.enq.valid := (inCnt.value < elements.length.U) && !flush - - when(q.io.deq.fire) { - assert(elems(outCnt) === q.io.deq.bits) - outCnt := outCnt + 1.U - } -} - -/** Test queue can enqueue during a flush - * - * @param elements The sequence of elements used in the queue - * @param queueDepth The max number of entries in the queue - * @param bitWidth Integer size of the data type used in the queue - * @param tap Integer tap('seed') for the LFSR - * @param useSyncReadMem True uses SyncReadMem instead of Mem as an internal memory element - */ -class EnqueueEmptyFlushEdgecaseTester( - elements: Seq[Int], - queueDepth: Int, - bitWidth: Int, - tap: Int, - useSyncReadMem: Boolean) - extends FlushQueueTesterBase(elements, queueDepth, bitWidth, tap, useSyncReadMem) { - val cycleCounter = Counter(elements.length + 1) - val outCounter = Counter(elements.length + 1) - - //testing an enqueue during a flush - flush := (cycleCounter.value === 0.U && inCnt.value === 0.U) //flushed only before anything is enqueued - cycleCounter.inc() //counts every cycle - - when(q.io.deq.fire) { - //flush and enqueue were both active on the first cycle, - //so that element is flushed immediately which makes outCnt off by one - assert(elems(outCounter.value + 1.U) === q.io.deq.bits) //ensure that what comes out is what comes in - outCounter.inc() - } -} - -/** Test queue can flush when full - * - * @param elements The sequence of elements used in the queue - * @param queueDepth The max number of entries in the queue - * @param bitWidth Integer size of the data type used in the queue - * @param tap Integer tap('seed') for the LFSR - * @param useSyncReadMem True uses SyncReadMem instead of Mem as an internal memory element - */ -class FullQueueFlushEdgecaseTester( - elements: Seq[Int], - queueDepth: Int, - bitWidth: Int, - tap: Int, - useSyncReadMem: Boolean) - extends FlushQueueTesterBase(elements, queueDepth, bitWidth, tap, useSyncReadMem) { - - //testing a flush when queue is full - flush := (currQCnt === queueDepth.U) - - when(q.io.deq.fire) { - //ensure that what comes out is what comes in - assert(currQCnt <= queueDepth.U) - assert(elems(outCnt) === q.io.deq.bits) - outCnt := outCnt + 1.U - when(currQCnt > 0.U) { - currQCnt := currQCnt - 1.U - } - } - when(flush) { - outCnt := outCnt + currQCnt - currQCnt := 0.U //resets the number of items currently inside queue - assert(currQCnt === 0.U || q.io.deq.valid) - } -} - -/** Test queue can dequeue on the same cycle as a flush - * - * @param elements The sequence of elements used in the queue - * @param queueDepth The max number of entries in the queue - * @param bitWidth Integer size of the data type used in the queue - * @param tap Integer tap('seed') for the LFSR - * @param useSyncReadMem True uses SyncReadMem instead of Mem as an internal memory element - */ -class DequeueFullQueueEdgecaseTester( - elements: Seq[Int], - queueDepth: Int, - bitWidth: Int, - tap: Int, - useSyncReadMem: Boolean) - extends FlushQueueTesterBase(elements, queueDepth, bitWidth, tap, useSyncReadMem) { - //Queue should be able to dequeue when queue is not empty and flush is high - - //testing a flush when dequeue is called - flush := currQCnt === (queueDepth / 2).U - q.io.enq.valid := !flushRegister - q.io.deq.ready := flush - - when(q.io.deq.fire) { - //ensure that what comes out is what comes in - assert(currQCnt <= queueDepth.U) - assert(elems(outCnt) === q.io.deq.bits) - assert(currQCnt > 0.U) - } - when(flush) { - //The outcount register is one count behind because the dequeue happens at the same time as the flush - outCnt := outCnt + currQCnt + 1.U - currQCnt := 0.U //resets the number of items currently inside queue - assert(currQCnt === 0.U || q.io.deq.valid) - } - when(flushRegister) { - //check that queue gets flushed when queue is full - assert(q.io.deq.fire === false.B) - } - -} - -class QueueFlushSpec extends ChiselPropSpec { - // Disable shrinking on error. - implicit val noShrinkListVal = Shrink[List[Int]](_ => Stream.empty) - implicit val noShrinkInt = Shrink[Int](_ => Stream.empty) - - property("Queue should have things pass through") { - forAll(vecSizes, safeUIntN(20), Gen.choose(0, 15), Gen.oneOf(true, false)) { (depth, se, tap, isSync) => - whenever(se._1 >= 1 && depth >= 1 && se._2.nonEmpty) { - assertTesterPasses { - new ThingsPassThroughFlushQueueTester(se._2, depth, se._1, tap, isSync) - } - } - } - } - property("Queue should flush when requested") { - forAll(vecSizes, safeUIntN(20), Gen.choose(0, 15), Gen.oneOf(true, false)) { (depth, se, tap, isSync) => - whenever(se._1 >= 1 && depth >= 1 && se._2.nonEmpty) { - assertTesterPasses { - new QueueGetsFlushedTester(se._2, depth, se._1, tap, isSync) - } - } - } - } - property("Queue flush when queue is empty") { - forAll(vecSizes, safeUIntN(20), Gen.choose(0, 15), Gen.oneOf(true, false)) { (depth, se, tap, isSync) => - whenever(se._1 >= 1 && depth >= 1 && se._2.nonEmpty) { - assertTesterPasses { - new EmptyFlushEdgecaseTester(se._2, depth, se._1, tap, isSync) - } - } - } - } - property("Test queue can enqueue during a flush") { - forAll(vecSizes, safeUIntN(20), Gen.choose(0, 15), Gen.oneOf(true, false)) { (depth, se, tap, isSync) => - whenever(se._1 >= 1 && depth >= 1 && se._2.nonEmpty) { - assertTesterPasses { - new EnqueueEmptyFlushEdgecaseTester(se._2, depth, se._1, tap, isSync) - } - } - } - } - property("Queue flush when queue is full") { - forAll(vecSizes, safeUIntN(20), Gen.choose(0, 15), Gen.oneOf(true, false)) { (depth, se, tap, isSync) => - whenever(se._1 >= 1 && depth >= 1 && se._2.nonEmpty) { - assertTesterPasses { - new FullQueueFlushEdgecaseTester(se._2, depth, se._1, tap, isSync) - } - } - } - } - property("Queue should be able to dequeue when flush is high") { - forAll(Gen.choose(3, 5), safeUIntN(20), Gen.choose(0, 15), Gen.oneOf(true, false)) { (depth, se, tap, isSync) => - whenever(se._1 >= 1 && depth >= 1 && se._2.nonEmpty) { - assertTesterPasses( - new DequeueFullQueueEdgecaseTester(se._2, depth, se._1, tap, isSync), - annotations = Seq(WriteVcdAnnotation) - ) - } - } - } -} diff --git a/src/test/scala/chiselTests/QueueSpec.scala b/src/test/scala/chiselTests/QueueSpec.scala deleted file mode 100644 index eaeb7f01..00000000 --- a/src/test/scala/chiselTests/QueueSpec.scala +++ /dev/null @@ -1,294 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import org.scalacheck._ - -import chisel3._ -import chisel3.testers.BasicTester -import chisel3.util._ -import chisel3.util.random.LFSR - -class ThingsPassThroughTester( - elements: Seq[Int], - queueDepth: Int, - bitWidth: Int, - tap: Int, - useSyncReadMem: Boolean, - hasFlush: Boolean) - extends BasicTester { - val q = Module(new Queue(UInt(bitWidth.W), queueDepth, useSyncReadMem = useSyncReadMem, hasFlush = hasFlush)) - val elems = VecInit(elements.map { - _.asUInt() - }) - val inCnt = Counter(elements.length + 1) - val outCnt = Counter(elements.length + 1) - - q.io.enq.valid := (inCnt.value < elements.length.U) - q.io.deq.ready := LFSR(16)(tap) - q.io.flush.foreach { _ := false.B } //Flush behavior is tested in QueueFlushSpec - q.io.enq.bits := elems(inCnt.value) - when(q.io.enq.fire) { - inCnt.inc() - } - when(q.io.deq.fire) { - //ensure that what comes out is what comes in - assert(elems(outCnt.value) === q.io.deq.bits) - outCnt.inc() - } - when(outCnt.value === elements.length.U) { - stop() - } -} - -class QueueReasonableReadyValid(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) - extends BasicTester { - val q = Module(new Queue(UInt(bitWidth.W), queueDepth, useSyncReadMem = useSyncReadMem)) - val elems = VecInit(elements.map { - _.asUInt() - }) - val inCnt = Counter(elements.length + 1) - val outCnt = Counter(elements.length + 1) - - q.io.enq.valid := (inCnt.value < elements.length.U) - //Queue should be full or ready - assert(q.io.enq.ready || q.io.count === queueDepth.U) - - q.io.deq.ready := LFSR(16)(tap) - //Queue should be empty or valid - assert(q.io.deq.valid || q.io.count === 0.U) - - q.io.enq.bits := elems(inCnt.value) - when(q.io.enq.fire) { - inCnt.inc() - } - when(q.io.deq.fire) { - outCnt.inc() - } - when(outCnt.value === elements.length.U) { - stop() - } -} - -class CountIsCorrectTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) - extends BasicTester { - val q = Module(new Queue(UInt(bitWidth.W), queueDepth, useSyncReadMem = useSyncReadMem)) - val elems = VecInit(elements.map { - _.asUInt(bitWidth.W) - }) - val inCnt = Counter(elements.length + 1) - val outCnt = Counter(elements.length + 1) - - q.io.enq.valid := (inCnt.value < elements.length.U) - q.io.deq.ready := LFSR(16)(tap) - - q.io.enq.bits := elems(inCnt.value) - when(q.io.enq.fire) { - inCnt.inc() - assert(q.io.count === (inCnt.value - outCnt.value)) - } - when(q.io.deq.fire) { - outCnt.inc() - assert(q.io.count === (inCnt.value - outCnt.value)) - } - //assert(q.io.count === (inCnt.value - outCnt.value)) - - when(outCnt.value === elements.length.U) { - stop() - } -} - -class QueueSinglePipeTester(elements: Seq[Int], bitWidth: Int, tap: Int, useSyncReadMem: Boolean) extends BasicTester { - val q = Module(new Queue(UInt(bitWidth.W), 1, pipe = true, useSyncReadMem = useSyncReadMem)) - val elems = VecInit(elements.map { - _.asUInt(bitWidth.W) - }) - val inCnt = Counter(elements.length + 1) - val outCnt = Counter(elements.length + 1) - - q.io.enq.valid := (inCnt.value < elements.length.U) - q.io.deq.ready := LFSR(16)(tap) - - assert(q.io.enq.ready || (q.io.count === 1.U && !q.io.deq.ready)) - - q.io.enq.bits := elems(inCnt.value) - when(q.io.enq.fire) { - inCnt.inc() - } - when(q.io.deq.fire) { - outCnt.inc() - } - - when(outCnt.value === elements.length.U) { - stop() - } -} - -class QueuePipeTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) - extends BasicTester { - val q = Module(new Queue(UInt(bitWidth.W), queueDepth, pipe = true, useSyncReadMem = useSyncReadMem)) - val elems = VecInit(elements.map { - _.asUInt(bitWidth.W) - }) - val inCnt = Counter(elements.length + 1) - val outCnt = Counter(elements.length + 1) - - q.io.enq.valid := (inCnt.value < elements.length.U) - q.io.deq.ready := LFSR(16)(tap) - - assert(q.io.enq.ready || (q.io.count === queueDepth.U && !q.io.deq.ready)) - - q.io.enq.bits := elems(inCnt.value) - when(q.io.enq.fire) { - inCnt.inc() - } - when(q.io.deq.fire) { - outCnt.inc() - } - - when(outCnt.value === elements.length.U) { - stop() - } -} - -class QueueFlowTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) - extends BasicTester { - val q = Module(new Queue(UInt(bitWidth.W), queueDepth, flow = true, useSyncReadMem = useSyncReadMem)) - val elems = VecInit(elements.map { - _.asUInt() - }) - val inCnt = Counter(elements.length + 1) - val outCnt = Counter(elements.length + 1) - - q.io.enq.valid := (inCnt.value < elements.length.U) - //Queue should be full or ready - assert(q.io.enq.ready || q.io.count === queueDepth.U) - - q.io.deq.ready := LFSR(16)(tap) - //Queue should be empty or valid - assert(q.io.deq.valid || (q.io.count === 0.U && !q.io.enq.fire)) - - q.io.enq.bits := elems(inCnt.value) - when(q.io.enq.fire) { - inCnt.inc() - } - when(q.io.deq.fire) { - outCnt.inc() - } - when(outCnt.value === elements.length.U) { - stop() - } -} - -class QueueFactoryTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: Int, useSyncReadMem: Boolean) - extends BasicTester { - val enq = Wire(Decoupled(UInt(bitWidth.W))) - val deq = Queue(enq, queueDepth, useSyncReadMem = useSyncReadMem) - - val elems = VecInit(elements.map { - _.asUInt() - }) - val inCnt = Counter(elements.length + 1) - val outCnt = Counter(elements.length + 1) - - enq.valid := (inCnt.value < elements.length.U) - deq.ready := LFSR(16)(tap) - - enq.bits := elems(inCnt.value) - when(enq.fire) { - inCnt.inc() - } - when(deq.fire) { - //ensure that what comes out is what comes in - assert(elems(outCnt.value) === deq.bits) - outCnt.inc() - } - when(outCnt.value === elements.length.U) { - stop() - } -} - -class QueueSpec extends ChiselPropSpec { - // Disable shrinking on error. - implicit val noShrinkListVal = Shrink[List[Int]](_ => Stream.empty) - implicit val noShrinkInt = Shrink[Int](_ => Stream.empty) - - property("Queue should have things pass through") { - forAll(vecSizes, safeUIntN(20), Gen.choose(0, 15), Gen.oneOf(true, false)) { (depth, se, tap, isSync) => - whenever(se._1 >= 1 && depth >= 1 && se._2.nonEmpty) { - assertTesterPasses { - new ThingsPassThroughTester(se._2, depth, se._1, tap, isSync, false) - } - } - } - } - - property("Queue should have reasonable ready/valid") { - forAll(vecSizes, safeUIntN(20), Gen.choose(0, 15), Gen.oneOf(true, false)) { (depth, se, tap, isSync) => - whenever(se._1 >= 1 && depth >= 1 && se._2.nonEmpty) { - assertTesterPasses { - new QueueReasonableReadyValid(se._2, depth, se._1, tap, isSync) - } - } - } - } - - property("Queue should have correct count") { - forAll(vecSizes, safeUIntN(20), Gen.choose(0, 15), Gen.oneOf(true, false)) { (depth, se, tap, isSync) => - whenever(se._1 >= 1 && depth >= 1 && se._2.nonEmpty) { - assertTesterPasses { - new CountIsCorrectTester(se._2, depth, se._1, tap, isSync) - } - } - } - } - - property("Queue pipe should work for 1-element queues") { - forAll(safeUIntN(20), Gen.choose(0, 15), Gen.oneOf(true, false)) { (se, tap, isSync) => - whenever(se._1 >= 1 && se._2.nonEmpty) { - assertTesterPasses { - new QueueSinglePipeTester(se._2, se._1, tap, isSync) - } - } - } - } - - property("Queue pipe should work for more general queues") { - forAll(vecSizes, safeUIntN(20), Gen.choose(0, 15), Gen.oneOf(true, false)) { (depth, se, tap, isSync) => - whenever(se._1 >= 1 && depth >= 1 && se._2.nonEmpty) { - assertTesterPasses { - new QueuePipeTester(se._2, depth, se._1, tap, isSync) - } - } - } - } - - property("Queue flow should work") { - forAll(vecSizes, safeUIntN(20), Gen.choose(0, 15), Gen.oneOf(true, false)) { (depth, se, tap, isSync) => - whenever(se._1 >= 1 && depth >= 1 && se._2.nonEmpty) { - assertTesterPasses { - new QueueFlowTester(se._2, depth, se._1, tap, isSync) - } - } - } - } - - property("Queue companion object factory method should work") { - forAll(vecSizes, safeUIntN(20), Gen.choose(0, 15), Gen.oneOf(true, false)) { (depth, se, tap, isSync) => - whenever(se._1 >= 1 && se._2.nonEmpty) { - assertTesterPasses { - new QueueFactoryTester(se._2, depth, se._1, tap, isSync) - } - } - } - } - - property("Queue.irrevocable should elaborate") { - class IrrevocableQueue extends Module { - val in = Wire(Decoupled(Bool())) - val iQueue = Queue.irrevocable(in, 1) - } - (new chisel3.stage.phases.Elaborate) - .transform(Seq(chisel3.stage.ChiselGeneratorAnnotation(() => new IrrevocableQueue))) - } -} diff --git a/src/test/scala/chiselTests/RangeSpec.scala b/src/test/scala/chiselTests/RangeSpec.scala deleted file mode 100644 index bc723bf6..00000000 --- a/src/test/scala/chiselTests/RangeSpec.scala +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.experimental.ChiselRange -import chisel3.internal.firrtl._ -import firrtl.ir.{Closed, Open} -import org.scalatest.freespec.AnyFreeSpec -import org.scalatest.matchers.should.Matchers - -class RangeSpec extends AnyFreeSpec with Matchers {} diff --git a/src/test/scala/chiselTests/RawModuleSpec.scala b/src/test/scala/chiselTests/RawModuleSpec.scala deleted file mode 100644 index 95687e82..00000000 --- a/src/test/scala/chiselTests/RawModuleSpec.scala +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.testers.BasicTester - -class UnclockedPlusOne extends RawModule { - val in = IO(Input(UInt(32.W))) - val out = IO(Output(UInt(32.W))) - - out := in + 1.asUInt -} - -class RawModuleTester extends BasicTester { - val plusModule = Module(new UnclockedPlusOne) - plusModule.in := 42.U - assert(plusModule.out === 43.U) - stop() -} - -class PlusOneModule extends Module { - val io = IO(new Bundle { - val in = Input(UInt(32.W)) - val out = Output(UInt(32.W)) - }) - io.out := io.in + 1.asUInt -} - -class RawModuleWithImplicitModule extends RawModule { - val in = IO(Input(UInt(32.W))) - val out = IO(Output(UInt(32.W))) - val clk = IO(Input(Clock())) - val rst = IO(Input(Bool())) - - withClockAndReset(clk, rst) { - val plusModule = Module(new PlusOneModule) - plusModule.io.in := in - out := plusModule.io.out - } -} - -class ImplicitModuleInRawModuleTester extends BasicTester { - val plusModule = Module(new RawModuleWithImplicitModule) - plusModule.clk := clock - plusModule.rst := reset - plusModule.in := 42.U - assert(plusModule.out === 43.U) - stop() -} - -class RawModuleWithDirectImplicitModule extends RawModule { - val plusModule = Module(new PlusOneModule) -} - -class ImplicitModuleDirectlyInRawModuleTester extends BasicTester { - val plusModule = Module(new RawModuleWithDirectImplicitModule) - stop() -} - -class RawModuleSpec extends ChiselFlatSpec with Utils { - "RawModule" should "elaborate" in { - ChiselStage.elaborate { new RawModuleWithImplicitModule } - } - - "RawModule" should "work" in { - assertTesterPasses({ new RawModuleTester }) - } - - "ImplicitModule in a withClock block in a RawModule" should "work" in { - assertTesterPasses({ new ImplicitModuleInRawModuleTester }) - } - - "ImplicitModule directly in a RawModule" should "fail" in { - intercept[chisel3.internal.ChiselException] { - extractCause[ChiselException] { - ChiselStage.elaborate { new RawModuleWithDirectImplicitModule } - } - } - } - - "ImplicitModule directly in a RawModule in an ImplicitModule" should "fail" in { - intercept[chisel3.internal.ChiselException] { - extractCause[ChiselException] { - ChiselStage.elaborate { new ImplicitModuleDirectlyInRawModuleTester } - } - } - } -} diff --git a/src/test/scala/chiselTests/RebindingSpec.scala b/src/test/scala/chiselTests/RebindingSpec.scala deleted file mode 100644 index 5dc0589e..00000000 --- a/src/test/scala/chiselTests/RebindingSpec.scala +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage - -class RebindingSpec extends ChiselFlatSpec with Utils { - "Rebinding a literal" should "fail" in { - a[BindingException] should be thrownBy extractCause[BindingException] { - ChiselStage.elaborate { - new Module { - val io = IO(new Bundle { - val a = 4.U - }) - } - } - } - } - - "Rebinding a hardware type" should "fail" in { - a[BindingException] should be thrownBy extractCause[BindingException] { - ChiselStage.elaborate { - new Module { - val io = IO(new Bundle { - val a = Reg(UInt(32.W)) - }) - } - } - } - } -} diff --git a/src/test/scala/chiselTests/RecordSpec.scala b/src/test/scala/chiselTests/RecordSpec.scala deleted file mode 100644 index 5a5bcf67..00000000 --- a/src/test/scala/chiselTests/RecordSpec.scala +++ /dev/null @@ -1,416 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.testers.BasicTester -import chisel3.util.{Counter, Queue} -import chisel3.experimental.{DataMirror, OpaqueType} - -import scala.collection.immutable.SeqMap - -trait RecordSpecUtils { - class MyBundle extends Bundle { - val foo = UInt(32.W) - val bar = UInt(32.W) - } - // Useful for constructing types from CustomBundle - // This is a def because each call to this needs to return a new instance - def fooBarType: CustomBundle = new CustomBundle("foo" -> UInt(32.W), "bar" -> UInt(32.W)) - - class MyModule(output: => Record, input: => Record) extends Module { - val io = IO(new Bundle { - val in = Input(input) - val out = Output(output) - }) - io.out <> io.in - } - - class ConnectionTestModule(output: => Record, input: => Record) extends Module { - val io = IO(new Bundle { - val inMono = Input(input) - val outMono = Output(output) - val inBi = Input(input) - val outBi = Output(output) - }) - io.outMono := io.inMono - io.outBi <> io.inBi - } - - class RecordSerializationTest extends BasicTester { - val recordType = new CustomBundle("fizz" -> UInt(16.W), "buzz" -> UInt(16.W)) - val record = Wire(recordType) - // Note that "buzz" was added later than "fizz" and is therefore higher order - record("fizz") := "hdead".U - record("buzz") := "hbeef".U - // To UInt - val uint = record.asUInt - assert(uint.getWidth == 32) // elaboration time - assert(uint === "hbeefdead".U) - // Back to Record - val record2 = uint.asTypeOf(recordType) - assert("hdead".U === record2("fizz").asUInt) - assert("hbeef".U === record2("buzz").asUInt) - stop() - } - - class RecordQueueTester extends BasicTester { - val queue = Module(new Queue(fooBarType, 4)) - queue.io <> DontCare - queue.io.enq.valid := false.B - val (cycle, done) = Counter(true.B, 4) - - when(cycle === 0.U) { - queue.io.enq.bits("foo") := 1234.U - queue.io.enq.bits("bar") := 5678.U - queue.io.enq.valid := true.B - } - when(cycle === 1.U) { - queue.io.deq.ready := true.B - assert(queue.io.deq.valid === true.B) - assert(queue.io.deq.bits("foo").asUInt === 1234.U) - assert(queue.io.deq.bits("bar").asUInt === 5678.U) - } - when(done) { - stop() - } - } - - class AliasedRecord extends Module { - val field = UInt(32.W) - val io = IO(new CustomBundle("in" -> Input(field), "out" -> Output(field))) - } - - class RecordIOModule extends Module { - val io = IO(new CustomBundle("in" -> Input(UInt(32.W)), "out" -> Output(UInt(32.W)))) - io("out") := io("in") - } - - class RecordIOTester extends BasicTester { - val mod = Module(new RecordIOModule) - mod.io("in") := 1234.U - assert(mod.io("out").asUInt === 1234.U) - stop() - } - - class RecordDigitTester extends BasicTester { - val wire = Wire(new CustomBundle("0" -> UInt(32.W))) - wire("0") := 123.U - assert(wire("0").asUInt === 123.U) - stop() - } - - class RecordTypeTester extends BasicTester { - val wire0 = Wire(new CustomBundle("0" -> UInt(32.W))) - val wire1 = Reg(new CustomBundle("0" -> UInt(32.W))) - val wire2 = Wire(new CustomBundle("1" -> UInt(32.W))) - require(DataMirror.checkTypeEquivalence(wire0, wire1)) - require(!DataMirror.checkTypeEquivalence(wire1, wire2)) - } - - class SingleElementRecord extends Record with OpaqueType { - private val underlying = UInt(8.W) - val elements = SeqMap("" -> underlying) - override def cloneType: this.type = (new SingleElementRecord).asInstanceOf[this.type] - - def +(that: SingleElementRecord): SingleElementRecord = { - val _w = Wire(new SingleElementRecord) - _w.underlying := this.underlying + that.underlying - _w - } - } - - class SingleElementRecordModule extends Module { - val in1 = IO(Input(new SingleElementRecord)) - val in2 = IO(Input(new SingleElementRecord)) - val out = IO(Output(new SingleElementRecord)) - - val r = new SingleElementRecord - - out := in1 + in2 - } - - class InnerRecord extends Record with OpaqueType { - val k = new InnerInnerRecord - val elements = SeqMap("" -> k) - override def cloneType: this.type = (new InnerRecord).asInstanceOf[this.type] - } - - class InnerInnerRecord extends Record with OpaqueType { - val k = new SingleElementRecord - val elements = SeqMap("" -> k) - override def cloneType: this.type = (new InnerInnerRecord).asInstanceOf[this.type] - } - - class NestedRecordModule extends Module { - val in = IO(Input(new InnerRecord)) - val out = IO(Output(new InnerRecord)) - val inst = Module(new InnerModule) - inst.io.foo := in - out := inst.io.bar - } - class InnerModule extends Module { - val io = IO(new Bundle { - val foo = Input(new InnerRecord) - val bar = Output(new InnerRecord) - }) - - // DO NOT do this; just for testing element connections - io.bar.elements.head._2 := io.foo.elements.head._2 - } - - class NamedSingleElementRecord extends Record with OpaqueType { - private val underlying = UInt(8.W) - val elements = SeqMap("unused" -> underlying) - - override def cloneType: this.type = (new NamedSingleElementRecord).asInstanceOf[this.type] - } - - class NamedSingleElementModule extends Module { - val in = IO(Input(new NamedSingleElementRecord)) - val out = IO(Output(new NamedSingleElementRecord)) - out := in - } - - class ErroneousOverride extends Record with OpaqueType { - private val underlyingA = UInt(8.W) - private val underlyingB = UInt(8.W) - val elements = SeqMap("x" -> underlyingA, "y" -> underlyingB) - - override def opaqueType = true - override def cloneType: this.type = (new ErroneousOverride).asInstanceOf[this.type] - } - - class ErroneousOverrideModule extends Module { - val in = IO(Input(new ErroneousOverride)) - val out = IO(Output(new ErroneousOverride)) - out := in - } - - class NotActuallyOpaqueType extends Record with OpaqueType { - private val underlyingA = UInt(8.W) - private val underlyingB = UInt(8.W) - val elements = SeqMap("x" -> underlyingA, "y" -> underlyingB) - - override def opaqueType = false - override def cloneType: this.type = (new NotActuallyOpaqueType).asInstanceOf[this.type] - } - - class NotActuallyOpaqueTypeModule extends Module { - val in = IO(Input(new NotActuallyOpaqueType)) - val out = IO(Output(new NotActuallyOpaqueType)) - out := in - } - - // Illustrate how to dyanmically decide between OpaqueType or not - sealed trait MaybeBoxed[T <: Data] extends Record { - def underlying: T - def boxed: Boolean - } - object MaybeBoxed { - def apply[T <: Data](gen: T, boxed: Boolean): MaybeBoxed[T] = { - if (boxed) new Boxed(gen) else new Unboxed(gen) - } - } - class Boxed[T <: Data](gen: T) extends MaybeBoxed[T] { - def boxed = true - lazy val elements = SeqMap("underlying" -> gen.cloneType) - def underlying = elements.head._2 - override def cloneType: this.type = (new Boxed(gen)).asInstanceOf[this.type] - } - class Unboxed[T <: Data](gen: T) extends MaybeBoxed[T] with OpaqueType { - def boxed = false - lazy val elements = SeqMap("" -> gen.cloneType) - def underlying = elements.head._2 - override def cloneType: this.type = (new Unboxed(gen)).asInstanceOf[this.type] - } -} - -class RecordSpec extends ChiselFlatSpec with RecordSpecUtils with Utils { - behavior.of("Records") - - they should "bulk connect similarly to Bundles" in { - ChiselStage.elaborate { new MyModule(fooBarType, fooBarType) } - } - - they should "bulk connect to Bundles" in { - ChiselStage.elaborate { new MyModule(new MyBundle, fooBarType) } - } - - they should "emit FIRRTL bulk connects when possible" in { - val chirrtl = (new ChiselStage).emitChirrtl( - gen = new ConnectionTestModule(fooBarType, fooBarType) - ) - chirrtl should include("io.outMono <= io.inMono @[RecordSpec.scala") - chirrtl should include("io.outBi <= io.inBi @[RecordSpec.scala") - } - - they should "not allow aliased fields" in { - class AliasedFieldRecord extends Record { - val foo = UInt(8.W) - val elements = SeqMap("foo" -> foo, "bar" -> foo) - override def cloneType: AliasedFieldRecord.this.type = (new AliasedFieldRecord).asInstanceOf[this.type] - } - - val e = intercept[AliasedAggregateFieldException] { - ChiselStage.elaborate { - new Module { - val io = IO(new AliasedFieldRecord) - } - } - } - e.getMessage should include("contains aliased fields named (bar,foo)") - } - - they should "support OpaqueType for maps with single unnamed elements" in { - val singleElementChirrtl = ChiselStage.emitChirrtl { new SingleElementRecordModule } - singleElementChirrtl should include("input in1 : UInt<8>") - singleElementChirrtl should include("input in2 : UInt<8>") - singleElementChirrtl should include("add(in1, in2)") - } - - they should "work correctly for toTarget in nested OpaqueType Records" in { - var mod: NestedRecordModule = null - ChiselStage.elaborate { mod = new NestedRecordModule; mod } - val testStrings = Seq( - mod.inst.io.foo.toTarget.serialize, - mod.inst.io.foo.k.toTarget.serialize, - mod.inst.io.foo.k.k.toTarget.serialize, - mod.inst.io.foo.elements.head._2.toTarget.serialize, - mod.inst.io.foo.k.elements.head._2.toTarget.serialize, - mod.inst.io.foo.k.k.elements.head._2.toTarget.serialize - ) - testStrings.foreach(x => assert(x == "~NestedRecordModule|InnerModule>io.foo")) - } - - they should "work correctly with DataMirror in nested OpaqueType Records" in { - var mod: NestedRecordModule = null - ChiselStage.elaborate { mod = new NestedRecordModule; mod } - val ports = chisel3.experimental.DataMirror.fullModulePorts(mod.inst) - val expectedPorts = Seq( - ("clock", mod.inst.clock), - ("reset", mod.inst.reset), - ("io", mod.inst.io), - ("io_bar", mod.inst.io.bar), - ("io_bar", mod.inst.io.bar.k), - ("io_bar", mod.inst.io.bar.k.k), - ("io_bar", mod.inst.io.bar.k.k.elements.head._2), - ("io_foo", mod.inst.io.foo), - ("io_foo", mod.inst.io.foo.k), - ("io_foo", mod.inst.io.foo.k.k), - ("io_foo", mod.inst.io.foo.k.k.elements.head._2) - ) - ports shouldBe expectedPorts - } - - they should "work correctly when connecting nested OpaqueType elements" in { - val nestedRecordChirrtl = ChiselStage.emitChirrtl { new NestedRecordModule } - nestedRecordChirrtl should include("input in : UInt<8>") - nestedRecordChirrtl should include("output out : UInt<8>") - nestedRecordChirrtl should include("inst.io.foo <= in") - nestedRecordChirrtl should include("out <= inst.io.bar") - nestedRecordChirrtl should include("output io : { flip foo : UInt<8>, bar : UInt<8>}") - nestedRecordChirrtl should include("io.bar <= io.foo") - } - - they should "throw an error when map contains a named element and OpaqueType is mixed in" in { - (the[Exception] thrownBy extractCause[Exception] { - ChiselStage.elaborate { new NamedSingleElementModule } - }).getMessage should include("Opaque types must have exactly one element with an empty name") - } - - they should "throw an error when map contains more than one element and OpaqueType is mixed in" in { - (the[Exception] thrownBy extractCause[Exception] { - ChiselStage.elaborate { new ErroneousOverrideModule } - }).getMessage should include("Opaque types must have exactly one element with an empty name") - } - - they should "work correctly when an OpaqueType overrides the def as false" in { - val chirrtl = ChiselStage.emitChirrtl(new NotActuallyOpaqueTypeModule) - chirrtl should include("input in : { y : UInt<8>, x : UInt<8>}") - chirrtl should include("output out : { y : UInt<8>, x : UInt<8>}") - chirrtl should include("out <= in") - } - - they should "support conditional OpaqueTypes via traits and factory methods" in { - class MyModule extends Module { - val in0 = IO(Input(MaybeBoxed(UInt(8.W), true))) - val out0 = IO(Output(MaybeBoxed(UInt(8.W), true))) - val in1 = IO(Input(MaybeBoxed(UInt(8.W), false))) - val out1 = IO(Output(MaybeBoxed(UInt(8.W), false))) - out0 := in0 - out1 := in1 - } - val chirrtl = ChiselStage.emitChirrtl(new MyModule) - chirrtl should include("input in0 : { underlying : UInt<8>}") - chirrtl should include("input in1 : UInt<8>") - } - - they should "work with .toTarget" in { - var m: SingleElementRecordModule = null - ChiselStage.elaborate { m = new SingleElementRecordModule; m } - val q = m.in1.toTarget.toString - assert(q == "~SingleElementRecordModule|SingleElementRecordModule>in1") - } - - they should "work (but warn) with .toTarget on non-data OpaqueType Record" in { - var m: SingleElementRecordModule = null - ChiselStage.elaborate { m = new SingleElementRecordModule; m } - val (log, q) = grabLog(m.r.toTarget) - log should include(".toTarget of non-hardware Data is deprecated") - assert(q.toString == "~SingleElementRecordModule|SingleElementRecordModule>r") - } - - they should "follow UInt serialization/deserialization API" in { - assertTesterPasses { new RecordSerializationTest } - } - - they should "work as the type of a Queue" in { - assertTesterPasses { new RecordQueueTester } - } - - they should "work as the type of a Module's io" in { - assertTesterPasses { new RecordIOTester } - } - - they should "support digits as names of fields" in { - assertTesterPasses { new RecordDigitTester } - } - - "Bulk connect on Record" should "check that the fields match" in { - (the[ChiselException] thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { new MyModule(fooBarType, new CustomBundle("bar" -> UInt(32.W))) } - }).getMessage should include("Right Record missing field") - - (the[ChiselException] thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { new MyModule(new CustomBundle("bar" -> UInt(32.W)), fooBarType) } - }).getMessage should include("Left Record missing field") - } - - "CustomBundle" should "work like built-in aggregates" in { - ChiselStage.elaborate(new Module { - val gen = new CustomBundle("foo" -> UInt(32.W)) - val io = IO(Output(gen)) - val wire = Wire(gen) - io := wire - }) - } - - "CustomBundle" should "check the types" in { - ChiselStage.elaborate { new RecordTypeTester } - } - - "Record with unstable elements" should "error" in { - class MyRecord extends Record { - def elements = SeqMap("a" -> UInt(8.W)) - override def cloneType: this.type = (new MyRecord).asInstanceOf[this.type] - } - val e = the[ChiselException] thrownBy { - ChiselStage.elaborate(new Module { - val io = IO(Input(new MyRecord)) - }) - } - e.getMessage should include("does not return the same objects when calling .elements multiple times") - } -} diff --git a/src/test/scala/chiselTests/ReduceTreeSpec.scala b/src/test/scala/chiselTests/ReduceTreeSpec.scala deleted file mode 100644 index 3f078106..00000000 --- a/src/test/scala/chiselTests/ReduceTreeSpec.scala +++ /dev/null @@ -1,106 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.util._ -import chisel3.testers.BasicTester - -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) - }) - - 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)) - - a.ready := regState === idleA - b.ready := regState === idleB - out.valid := (regState === hasA || regState === hasB) - - switch(regState) { - is(idleA) { - when(a.valid) { - regData := a.bits - regState := hasA - }.otherwise { - regState := idleB - } - } - is(idleB) { - when(b.valid) { - regData := b.bits - regState := hasB - }.otherwise { - regState := idleA - } - } - is(hasA) { - when(out.ready) { - regState := idleB - } - } - is(hasB) { - when(out.ready) { - regState := idleA - } - } - } - - out.bits := regData.asUInt + 1.U - out - } - - io.out <> io.in.reduceTree(arbitrateTwo) -} - -class ReduceTreeBalancedTester(nodes: Int) extends BasicTester { - - val cnt = RegInit(0.U(8.W)) - val min = RegInit(99.U(8.W)) - val max = RegInit(0.U(8.W)) - - val dut = Module(new Arbiter(nodes, UInt(16.W))) - for (i <- 0 until nodes) { - dut.io.in(i).valid := true.B - dut.io.in(i).bits := 0.U - } - dut.io.out.ready := true.B - - when(dut.io.out.valid) { - val hops = dut.io.out.bits - when(hops < min) { - min := hops - } - when(hops > max) { - max := hops - } - } - - when(!(max === 0.U || min === 99.U)) { - assert(max - min <= 1.U) - } - - cnt := cnt + 1.U - when(cnt === 10.U) { - stop() - } -} - -class ReduceTreeBalancedSpec extends ChiselPropSpec { - property("Tree shall be fair and shall have a maximum difference of one hop for each node") { - - // This test will fail for 5 nodes due to an unbalanced tree. - // A fix is on the way. - for (n <- 1 to 5) { - assertTesterPasses { - new ReduceTreeBalancedTester(n) - } - } - } -} diff --git a/src/test/scala/chiselTests/Reg.scala b/src/test/scala/chiselTests/Reg.scala deleted file mode 100644 index c814a030..00000000 --- a/src/test/scala/chiselTests/Reg.scala +++ /dev/null @@ -1,91 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.util._ -import chisel3.experimental.DataMirror -import chisel3.stage.ChiselStage -import chisel3.testers.BasicTester -import org.scalacheck.Gen - -class RegSpec extends ChiselFlatSpec { - "Reg" should "be of the same type and width as t" in { - class RegOutTypeWidthTester extends BasicTester { - val reg = Reg(UInt(2.W)) - DataMirror.widthOf(reg) should be(2.W) - } - ChiselStage.elaborate { new RegOutTypeWidthTester } - } - - "RegNext" should "be of unknown width" in { - class RegUnknownWidthTester extends BasicTester { - val reg1 = RegNext(2.U(3.W)) - DataMirror.widthOf(reg1).known should be(false) - val reg2 = RegNext(2.U(3.W), 4.U) - DataMirror.widthOf(reg2).known should be(false) - val reg3 = RegNext(2.U(3.W), 4.U(5.W)) - DataMirror.widthOf(reg3).known should be(false) - } - ChiselStage.elaborate { new RegUnknownWidthTester } - } - - "RegInit" should "have width only if specified in the literal" in { - class RegForcedWidthTester extends BasicTester { - val reg1 = RegInit(20.U) - DataMirror.widthOf(reg1).known should be(false) - val reg2 = RegInit(20.U(7.W)) - DataMirror.widthOf(reg2) should be(7.W) - } - ChiselStage.elaborate { new RegForcedWidthTester } - } -} - -class ShiftTester(n: Int) extends BasicTester { - val (cntVal, done) = Counter(true.B, n) - val start = 23.U - val sr = ShiftRegister(cntVal + start, n) - when(done) { - assert(sr === start) - stop() - } -} - -class ShiftResetTester(n: Int) extends BasicTester { - val (cntVal, done) = Counter(true.B, n - 1) - val start = 23.U - val sr = ShiftRegister(cntVal + 23.U, n, 1.U, true.B) - when(done) { - assert(sr === (if (n == 0) cntVal + 23.U else 1.U)) - stop() - } -} - -class ShiftRegisterSpec extends ChiselPropSpec { - property("ShiftRegister should shift") { - forAll(Gen.choose(0, 4)) { (shift: Int) => assertTesterPasses { new ShiftTester(shift) } } - } - - property("ShiftRegister should reset all values inside") { - forAll(Gen.choose(0, 4)) { (shift: Int) => assertTesterPasses { new ShiftResetTester(shift) } } - } -} - -class ShiftsTester(n: Int) extends BasicTester { - val (cntVal, done) = Counter(true.B, n) - val start = 23.U - val srs = ShiftRegisters(cntVal + start, n) - when(RegNext(done)) { - srs.zipWithIndex.foreach { - case (data, index) => - assert(data === (23 + n - 1 - index).U) - } - stop() - } -} - -class ShiftRegistersSpec extends ChiselPropSpec { - property("ShiftRegisters should shift") { - forAll(Gen.choose(0, 4)) { (shift: Int) => assertTesterPasses { new ShiftsTester(shift) } } - } -} diff --git a/src/test/scala/chiselTests/ResetSpec.scala b/src/test/scala/chiselTests/ResetSpec.scala deleted file mode 100644 index fe0273b3..00000000 --- a/src/test/scala/chiselTests/ResetSpec.scala +++ /dev/null @@ -1,115 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.util.{Counter, Queue} -import chisel3.testers.BasicTester - -class ResetAgnosticModule extends RawModule { - val clk = IO(Input(Clock())) - val rst = IO(Input(Reset())) - val out = IO(Output(UInt(8.W))) - - val reg = withClockAndReset(clk, rst)(RegInit(0.U(8.W))) - reg := reg + 1.U - out := reg -} - -class AbstractResetDontCareModule extends RawModule { - import chisel3.util.Valid - val monoPort = IO(Output(Reset())) - monoPort := DontCare - val monoWire = Wire(Reset()) - monoWire := DontCare - val monoAggPort = IO(Output(Valid(Reset()))) - monoAggPort := DontCare - val monoAggWire = Wire(Valid(Reset())) - monoAggWire := DontCare - - // Can't bulk connect to Wire so only ports here - val bulkPort = IO(Output(Reset())) - bulkPort <> DontCare - val bulkAggPort = IO(Output(Valid(Reset()))) - bulkAggPort <> DontCare -} - -class ResetSpec extends ChiselFlatSpec with Utils { - - behavior.of("Reset") - - it should "be able to be connected to DontCare" in { - ChiselStage.elaborate(new AbstractResetDontCareModule) - } - - it should "be able to drive Bool" in { - ChiselStage.emitVerilog(new RawModule { - val in = IO(Input(Bool())) - val out = IO(Output(Bool())) - val w = Wire(Reset()) - w := in - out := w - }) - } - - it should "be able to drive AsyncReset" in { - ChiselStage.emitVerilog(new RawModule { - val in = IO(Input(AsyncReset())) - val out = IO(Output(AsyncReset())) - val w = Wire(Reset()) - w := in - out := w - }) - } - - it should "allow writing modules that are reset agnostic" in { - val sync = compile(new Module { - val io = IO(new Bundle { - val out = Output(UInt(8.W)) - }) - val inst = Module(new ResetAgnosticModule) - inst.clk := clock - inst.rst := reset - assert(inst.rst.isInstanceOf[chisel3.ResetType]) - io.out := inst.out - }) - sync should include("always @(posedge clk)") - - val async = compile(new Module { - val io = IO(new Bundle { - val out = Output(UInt(8.W)) - }) - val inst = Module(new ResetAgnosticModule) - inst.clk := clock - inst.rst := reset.asTypeOf(AsyncReset()) - assert(inst.rst.isInstanceOf[chisel3.ResetType]) - io.out := inst.out - }) - async should include("always @(posedge clk or posedge rst)") - } - - behavior.of("Users") - - they should "be able to force implicit reset to be synchronous" in { - 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 Module with RequireAsyncReset { - reset shouldBe an[AsyncReset] - }) - fir should include("input reset : AsyncReset") - } - - "Chisel" should "error if sync and async modules are nested" in { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate(new Module with RequireAsyncReset { - val mod = Module(new Module with RequireSyncReset) - }) - } - } -} diff --git a/src/test/scala/chiselTests/Risc.scala b/src/test/scala/chiselTests/Risc.scala deleted file mode 100644 index e0eacb90..00000000 --- a/src/test/scala/chiselTests/Risc.scala +++ /dev/null @@ -1,123 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.util._ - -class Risc extends Module { - val io = IO(new Bundle { - val isWr = Input(Bool()) - val wrAddr = Input(UInt(8.W)) - val wrData = Input(Bits(32.W)) - val boot = Input(Bool()) - val valid = Output(Bool()) - val out = Output(Bits(32.W)) - }) - val memSize = 256 - val file = Mem(memSize, Bits(32.W)) - val code = Mem(memSize, Bits(32.W)) - val pc = RegInit(0.U(8.W)) - - val add_op :: imm_op :: Nil = Enum(2) - - val inst = code(pc) - val op = inst(31, 24) - val rci = inst(23, 16) - val rai = inst(15, 8) - val rbi = inst(7, 0) - - val ra = Mux(rai === 0.U, 0.U, file(rai)) - val rb = Mux(rbi === 0.U, 0.U, file(rbi)) - val rc = Wire(Bits(32.W)) - - io.valid := false.B - io.out := 0.U - rc := 0.U - - when(io.isWr) { - code(io.wrAddr) := io.wrData - }.elsewhen(io.boot) { - pc := 0.U - }.otherwise { - switch(op) { - is(add_op) { rc := ra +% rb } - is(imm_op) { rc := (rai << 8) | rbi } - } - io.out := rc - when(rci === 255.U) { - io.valid := true.B - }.otherwise { - file(rci) := rc - } - pc := pc +% 1.U - } -} - -/* -class RiscTester(c: Risc) extends Tester(c) { - def wr(addr: BigInt, data: BigInt) = { - poke(c.io.isWr, 1) - poke(c.io.wrAddr, addr) - poke(c.io.wrData, data) - step(1) - } - def boot() = { - poke(c.io.isWr, 0) - poke(c.io.boot, 1) - step(1) - } - def tick(isBoot: Boolean) = { - if (isBoot) - poke(c.io.boot, 0) - step(1) - } - def I (op: UInt, rc: Int, ra: Int, rb: Int) = { - // val cr = Cat(op, rc.asUInt(8.W), ra.asUInt(8.W), rb.asUInt(8.W)).litValue() - val cr = op.litValue() << 24 | rc << 16 | ra << 8 | rb - println("I = " + cr) - cr - } - - val app = Array(I(c.imm_op, 1, 0, 1), // r1 <- 1 - I(c.add_op, 1, 1, 1), // r1 <- r1 + r1 - I(c.add_op, 1, 1, 1), // r1 <- r1 + r1 - I(c.add_op, 255, 1, 0)) // rh <- r1 - wr(0, 0) // skip reset - for (addr <- 0 until app.length) - wr(addr, app(addr)) - def dump(k: Int) { - println("K = " + k) - peek(c.ra) - peek(c.rb) - peek(c.rc) - peek(c.io.out) - peek(c.pc) - peek(c.inst) - peek(c.op) - peek(c.rci) - peek(c.rai) - peek(c.rbi) - peekAt(c.file, 1) - } - boot() - dump(0) - var k = 0 - do { - tick(k == 0); k += 1 - dump(k) - } while (!(peek(c.io.valid) == 1 || k > 10)) - expect(k <= 10, "TIME LIMIT") - expect(c.io.out, 4) -} - */ - -class RiscSpec extends ChiselPropSpec { - - property("Risc should elaborate") { - ChiselStage.elaborate { new Risc } - } - - ignore("RiscTester should return the correct result") {} -} diff --git a/src/test/scala/chiselTests/SIntOps.scala b/src/test/scala/chiselTests/SIntOps.scala deleted file mode 100644 index ebbd2012..00000000 --- a/src/test/scala/chiselTests/SIntOps.scala +++ /dev/null @@ -1,151 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.testers.BasicTester - -class SIntOps extends Module { - val io = IO(new Bundle { - val a = Input(SInt(16.W)) - val b = Input(SInt(16.W)) - val addout = Output(SInt(16.W)) - val subout = Output(SInt(16.W)) - val timesout = Output(SInt(16.W)) - val divout = Output(SInt(16.W)) - val modout = Output(SInt(16.W)) - val lshiftout = Output(SInt(16.W)) - val rshiftout = Output(SInt(16.W)) - val lessout = Output(Bool()) - val greatout = Output(Bool()) - val eqout = Output(Bool()) - val noteqout = Output(Bool()) - val lesseqout = Output(Bool()) - val greateqout = Output(Bool()) - val negout = Output(SInt(16.W)) - }) - - val a = io.a - val b = io.b - - io.addout := a +% b - io.subout := a -% b - // TODO: - //io.timesout := (a * b)(15, 0) - //io.divout := a / Mux(b === 0.S, 1.S, b) - //io.divout := (a / b)(15, 0) - //io.modout := 0.S - //io.lshiftout := (a << 12)(15, 0) // (a << ub(3, 0))(15, 0).toSInt - io.rshiftout := (a >> 8) // (a >> ub).toSInt - io.lessout := a < b - io.greatout := a > b - io.eqout := a === b - io.noteqout := (a =/= b) - io.lesseqout := a <= b - io.greateqout := a >= b - io.negout := -a(15, 0).asSInt - io.negout := (0.S -% a) -} - -/* -class SIntOpsTester(c: SIntOps) extends Tester(c) { - def sintExpect(d: Bits, x: BigInt) { - val mask = (1 << 16) - 1 - val sbit = (1 << 15) - val y = x & mask - val r = if ((y & sbit) == 0) y else (-(~y)-1) - expect(d, r) - } - for (t <- 0 until 16) { - val test_a = (1 << 15) - rnd.nextInt(1 << 16) - val test_b = (1 << 15) - rnd.nextInt(1 << 16) - poke(c.io.a, test_a) - poke(c.io.b, test_b) - step(1) - sintExpect(c.io.addout, test_a + test_b) - sintExpect(c.io.subout, test_a - test_b) - sintExpect(c.io.timesout, test_a * test_b) - // sintExpect(c.io.divout, if (test_b == 0) 0 else test_a / test_b) - sintExpect(c.io.divout, test_a * test_b) - // sintExpect(c.io.modout, test_a % test_b) - // sintExpect(c.io.lshiftout, test_a << (test_b&15)) - // sintExpect(c.io.rshiftout, test_a >> test_b) - sintExpect(c.io.lshiftout, test_a << 12) - sintExpect(c.io.rshiftout, test_a >> 8) - sintExpect(c.io.negout, -test_a) - expect(c.io.lessout, int(test_a < test_b)) - expect(c.io.greatout, int(test_a > test_b)) - expect(c.io.eqout, int(test_a == test_b)) - expect(c.io.noteqout, int(test_a != test_b)) - expect(c.io.lessout, int(test_a <= test_b)) - expect(c.io.greateqout, int(test_a >= test_b)) - } -} - */ - -class SIntLitExtractTester extends BasicTester { - assert(-5.S.extract(1) === true.B) - assert(-5.S.extract(2) === false.B) - assert(-5.S.extract(100) === true.B) - assert(-5.S(3, 0) === "b1011".U) - assert(-5.S(9, 0) === "b1111111011".U) - assert(-5.S(4.W)(1) === true.B) - assert(-5.S(4.W)(2) === false.B) - assert(-5.S(4.W)(100) === true.B) - assert(-5.S(4.W)(3, 0) === "b1011".U) - assert(-5.S(4.W)(9, 0) === "b1111111011".U) - stop() -} - -class SIntOpsSpec extends ChiselPropSpec with Utils { - - property("SIntOps should elaborate") { - ChiselStage.elaborate { new SIntOps } - } - - property("Negative shift amounts are invalid") { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate(new NegativeShift(SInt())) - } - } - - ignore("SIntOpsTester should return the correct result") {} - - property("Bit extraction on literals should work for all non-negative indices") { - assertTesterPasses(new SIntLitExtractTester) - } - - // We use WireDefault with 2 arguments because of - // https://www.chisel-lang.org/api/3.4.1/chisel3/WireDefault$.html - // Single Argument case 2 - property("modulo divide should give min width of arguments") { - assertKnownWidth(4) { - val x = WireDefault(SInt(8.W), DontCare) - val y = WireDefault(SInt(4.W), DontCare) - val op = x % y - WireDefault(chiselTypeOf(op), op) - } - assertKnownWidth(4) { - val x = WireDefault(SInt(4.W), DontCare) - val y = WireDefault(SInt(8.W), DontCare) - val op = x % y - WireDefault(chiselTypeOf(op), op) - } - } - - property("division should give the width of the numerator + 1") { - assertKnownWidth(9) { - val x = WireDefault(SInt(8.W), DontCare) - val y = WireDefault(SInt(4.W), DontCare) - val op = x / y - WireDefault(chiselTypeOf(op), op) - } - assertKnownWidth(5) { - val x = WireDefault(SInt(4.W), DontCare) - val y = WireDefault(SInt(8.W), DontCare) - val op = x / y - WireDefault(chiselTypeOf(op), op) - } - } -} diff --git a/src/test/scala/chiselTests/ScalaIntervalSimulatorTest.scala b/src/test/scala/chiselTests/ScalaIntervalSimulatorTest.scala deleted file mode 100644 index 94f5ccc7..00000000 --- a/src/test/scala/chiselTests/ScalaIntervalSimulatorTest.scala +++ /dev/null @@ -1,97 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.experimental._ -import org.scalatest.freespec.AnyFreeSpec -import org.scalatest.matchers.should.Matchers - -class ScalaIntervalSimulatorSpec extends AnyFreeSpec with Matchers { - "clip tests" - { - "Should work for closed ranges" in { - val sim = ScalaIntervalSimulator(range"[2,4]") - sim.clip(BigDecimal(1.0)) should be(2.0) - sim.clip(BigDecimal(2.0)) should be(2.0) - sim.clip(BigDecimal(3.0)) should be(3.0) - sim.clip(BigDecimal(4.0)) should be(4.0) - sim.clip(BigDecimal(5.0)) should be(4.0) - } - "Should work for closed ranges with binary point" in { - val sim = ScalaIntervalSimulator(range"[2,6].2") - sim.clip(BigDecimal(1.75)) should be(2.0) - sim.clip(BigDecimal(2.0)) should be(2.0) - sim.clip(BigDecimal(2.25)) should be(2.25) - sim.clip(BigDecimal(2.5)) should be(2.5) - sim.clip(BigDecimal(5.75)) should be(5.75) - sim.clip(BigDecimal(6.0)) should be(6.0) - sim.clip(BigDecimal(6.25)) should be(6.0) - sim.clip(BigDecimal(6.5)) should be(6.0) - sim.clip(BigDecimal(8.5)) should be(6.0) - } - "Should work for open ranges" in { - val sim = ScalaIntervalSimulator(range"(2,4)") - sim.clip(BigDecimal(1.0)) should be(3.0) - sim.clip(BigDecimal(2.0)) should be(3.0) - sim.clip(BigDecimal(3.0)) should be(3.0) - sim.clip(BigDecimal(4.0)) should be(3.0) - sim.clip(BigDecimal(5.0)) should be(3.0) - } - "Should work for open ranges with binary point" in { - val sim = ScalaIntervalSimulator(range"(2,6).2") - sim.clip(BigDecimal(1.75)) should be(2.25) - sim.clip(BigDecimal(2.0)) should be(2.25) - sim.clip(BigDecimal(2.25)) should be(2.25) - sim.clip(BigDecimal(2.5)) should be(2.5) - sim.clip(BigDecimal(5.75)) should be(5.75) - sim.clip(BigDecimal(6.0)) should be(5.75) - sim.clip(BigDecimal(6.25)) should be(5.75) - sim.clip(BigDecimal(6.5)) should be(5.75) - sim.clip(BigDecimal(8.5)) should be(5.75) - } - } - "wrap tests" - { - "Should work for closed ranges" in { - val sim = ScalaIntervalSimulator(range"[2,6]") - sim.wrap(BigDecimal(1.0)) should be(6.0) - sim.wrap(BigDecimal(2.0)) should be(2.0) - sim.wrap(BigDecimal(3.0)) should be(3.0) - sim.wrap(BigDecimal(4.0)) should be(4.0) - sim.wrap(BigDecimal(5.0)) should be(5.0) - sim.wrap(BigDecimal(6.0)) should be(6.0) - sim.wrap(BigDecimal(7.0)) should be(2.0) - } - "Should work for closed ranges with binary point" in { - val sim = ScalaIntervalSimulator(range"[2,6].2") - sim.wrap(BigDecimal(1.75)) should be(6.0) - sim.wrap(BigDecimal(2.0)) should be(2.0) - sim.wrap(BigDecimal(2.25)) should be(2.25) - sim.wrap(BigDecimal(2.5)) should be(2.5) - sim.wrap(BigDecimal(5.75)) should be(5.75) - sim.wrap(BigDecimal(6.0)) should be(6.0) - sim.wrap(BigDecimal(6.25)) should be(2.0) - sim.wrap(BigDecimal(6.5)) should be(2.25) - } - "Should work for open ranges" in { - val sim = ScalaIntervalSimulator(range"(2,6)") - sim.wrap(BigDecimal(1.0)) should be(4.0) - sim.wrap(BigDecimal(2.0)) should be(5.0) - sim.wrap(BigDecimal(3.0)) should be(3.0) - sim.wrap(BigDecimal(4.0)) should be(4.0) - sim.wrap(BigDecimal(5.0)) should be(5.0) - sim.wrap(BigDecimal(6.0)) should be(3.0) - sim.wrap(BigDecimal(7.0)) should be(4.0) - } - "Should work for open ranges with binary point" in { - val sim = ScalaIntervalSimulator(range"(2,6).2") - sim.wrap(BigDecimal(1.75)) should be(5.5) - sim.wrap(BigDecimal(2.0)) should be(5.75) - sim.wrap(BigDecimal(2.25)) should be(2.25) - sim.wrap(BigDecimal(2.5)) should be(2.5) - sim.wrap(BigDecimal(5.75)) should be(5.75) - sim.wrap(BigDecimal(6.0)) should be(2.25) - sim.wrap(BigDecimal(6.25)) should be(2.5) - sim.wrap(BigDecimal(7.0)) should be(3.25) - } - } -} diff --git a/src/test/scala/chiselTests/Stack.scala b/src/test/scala/chiselTests/Stack.scala deleted file mode 100644 index 085f4e34..00000000 --- a/src/test/scala/chiselTests/Stack.scala +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.util._ - -class ChiselStack(val depth: Int) extends Module { - val io = IO(new Bundle { - val push = Input(Bool()) - val pop = Input(Bool()) - val en = Input(Bool()) - val dataIn = Input(UInt(32.W)) - val dataOut = Output(UInt(32.W)) - }) - - val stack_mem = Mem(depth, UInt(32.W)) - val sp = RegInit(0.U(log2Ceil(depth + 1).W)) - val out = RegInit(0.U(32.W)) - - when(io.en) { - when(io.push && (sp < depth.asUInt)) { - stack_mem(sp) := io.dataIn - sp := sp +% 1.U - }.elsewhen(io.pop && (sp > 0.U)) { - sp := sp -% 1.U - } - when(sp > 0.U) { - out := stack_mem(sp -% 1.U) - } - } - io.dataOut := out -} - -/* -class StackTester(c: Stack) extends Tester(c) { - var nxtDataOut = 0 - var dataOut = 0 - val stack = new ScalaStack[Int]() - - for (t <- 0 until 16) { - val enable = rnd.nextInt(2) - val push = rnd.nextInt(2) - val pop = rnd.nextInt(2) - val dataIn = rnd.nextInt(256) - - if (enable == 1) { - dataOut = nxtDataOut - if (push == 1 && stack.length < c.depth) { - stack.push(dataIn) - } else if (pop == 1 && stack.length > 0) { - stack.pop() - } - if (stack.length > 0) { - nxtDataOut = stack.top - } - } - - poke(c.io.pop, pop) - poke(c.io.push, push) - poke(c.io.en, enable) - poke(c.io.dataIn, dataIn) - step(1) - expect(c.io.dataOut, dataOut) - } -} - */ - -class StackSpec extends ChiselPropSpec { - - property("Stack should elaborate") { - ChiselStage.elaborate { new ChiselStack(2) } - } - - ignore("StackTester should return the correct result") {} -} diff --git a/src/test/scala/chiselTests/Stop.scala b/src/test/scala/chiselTests/Stop.scala deleted file mode 100644 index 25aae2d9..00000000 --- a/src/test/scala/chiselTests/Stop.scala +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.testers.BasicTester - -class StopTester() extends BasicTester { - stop() -} - -class StopImmediatelyTester extends BasicTester { - val cycle = RegInit(0.asUInt(4.W)) - cycle := cycle + 1.U - when(cycle === 4.U) { - stop() - } - assert(cycle =/= 5.U, "Simulation did not exit upon executing stop()") -} - -class StopSpec extends ChiselFlatSpec { - "stop()" should "stop and succeed the testbench" in { - assertTesterPasses { new StopTester } - } - - it should "end the simulation immediately" in { - assertTesterPasses { new StopImmediatelyTester } - } -} diff --git a/src/test/scala/chiselTests/SwitchSpec.scala b/src/test/scala/chiselTests/SwitchSpec.scala deleted file mode 100644 index 52f50a53..00000000 --- a/src/test/scala/chiselTests/SwitchSpec.scala +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.util.{is, switch} - -class SwitchSpec extends ChiselFlatSpec with Utils { - "switch" should "require literal conditions" in { - a[java.lang.IllegalArgumentException] should be thrownBy extractCause[IllegalArgumentException] { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle {}) - val state = RegInit(0.U) - val wire = WireDefault(0.U) - switch(state) { - is(wire) { state := 1.U } - } - }) - } - } - it should "require mutually exclusive conditions" in { - a[java.lang.IllegalArgumentException] should be thrownBy extractCause[IllegalArgumentException] { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle {}) - val state = RegInit(0.U) - switch(state) { - is(0.U) { state := 1.U } - is(1.U) { state := 2.U } - is(0.U) { state := 3.U } - } - }) - } - } - it should "provide useful source locators" in { - val chirrtl = ChiselStage.emitChirrtl(new Module { - val io = IO(new Bundle { - val in = Input(UInt(2.W)) - val out = Output(UInt(2.W)) - }) - - io.out := 0.U - switch(io.in) { - is(0.U) { io.out := 3.U } - is(1.U) { io.out := 0.U } - is(2.U) { io.out := 1.U } - is(3.U) { io.out := 3.U } - } - }) - - (chirrtl should not).include("Conditional.scala") - } -} diff --git a/src/test/scala/chiselTests/Tbl.scala b/src/test/scala/chiselTests/Tbl.scala deleted file mode 100644 index 5e127770..00000000 --- a/src/test/scala/chiselTests/Tbl.scala +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.testers.BasicTester -import chisel3.util._ - -class Tbl(w: Int, n: Int) extends Module { - val io = IO(new Bundle { - val wi = Input(UInt(log2Ceil(n).W)) - val ri = Input(UInt(log2Ceil(n).W)) - val we = Input(Bool()) - val d = Input(UInt(w.W)) - val o = Output(UInt(w.W)) - }) - val m = Mem(n, UInt(w.W)) - io.o := m(io.ri) - when(io.we) { - m(io.wi) := io.d - when(io.ri === io.wi) { - io.o := io.d - } - } -} - -class TblTester(w: Int, n: Int, idxs: List[Int], values: List[Int]) extends BasicTester { - val (cnt, wrap) = Counter(true.B, idxs.size) - val dut = Module(new Tbl(w, n)) - val vvalues = VecInit(values.map(_.asUInt)) - val vidxs = VecInit(idxs.map(_.asUInt)) - val prev_idx = vidxs(cnt - 1.U) - val prev_value = vvalues(cnt - 1.U) - dut.io.wi := vidxs(cnt) - dut.io.ri := prev_idx - dut.io.we := true.B //TODO enSequence - dut.io.d := vvalues(cnt) - when(cnt > 0.U) { - when(prev_idx === vidxs(cnt)) { - assert(dut.io.o === vvalues(cnt)) - }.otherwise { - assert(dut.io.o === prev_value) - } - } - when(wrap) { - stop() - } -} - -class TblSpec extends ChiselPropSpec { - property("All table reads should return the previous write") { - forAll(safeUIntPairN(8)) { - case (w: Int, pairs: List[(Int, Int)]) => - // Provide an appropriate whenever clause. - // ScalaTest will try and shrink the values on error to determine the smallest values that cause the error. - whenever(w > 0 && pairs.length > 0) { - val (idxs, values) = pairs.unzip - assertTesterPasses { new TblTester(w, 1 << w, idxs, values) } - } - } - } -} diff --git a/src/test/scala/chiselTests/TesterDriverSpec.scala b/src/test/scala/chiselTests/TesterDriverSpec.scala deleted file mode 100644 index c3cc232f..00000000 --- a/src/test/scala/chiselTests/TesterDriverSpec.scala +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.testers.BasicTester -import chisel3.util._ - -/** Extend BasicTester with a simple circuit and finish method. TesterDriver will call the - * finish method after the FinishTester's constructor has completed, which will alter the - * circuit after the constructor has finished. - */ -class FinishTester extends BasicTester { - val test_wire_width = 2 - val test_wire_override_value = 3 - - val counter = Counter(1) - - when(counter.inc()) { - stop() - } - - val test_wire = WireDefault(1.U(test_wire_width.W)) - - // though we just set test_wire to 1, the assert below will pass because - // the finish will change its value - assert(test_wire === test_wire_override_value.asUInt) - - /** In finish we use last connect semantics to alter the test_wire in the circuit - * with a new value - */ - override def finish(): Unit = { - test_wire := test_wire_override_value.asUInt - } -} - -class TesterDriverSpec extends ChiselFlatSpec { - "TesterDriver calls BasicTester's finish method which" should - "allow modifications of test circuit after the tester's constructor is done" in { - assertTesterPasses { - new FinishTester - } - } -} diff --git a/src/test/scala/chiselTests/ToTargetSpec.scala b/src/test/scala/chiselTests/ToTargetSpec.scala deleted file mode 100644 index de46cdcb..00000000 --- a/src/test/scala/chiselTests/ToTargetSpec.scala +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.util.Queue -import chisel3.internal.ChiselException - -class ToTargetSpec extends ChiselFlatSpec with Utils { - - var m: InstanceNameModule = _ - ChiselStage.elaborate { m = new InstanceNameModule; m } - - val mn = "InstanceNameModule" - val top = s"~$mn|$mn" - - behavior.of(".toTarget") - - val deprecationMsg = "Accessing the .instanceName or .toTarget of non-hardware Data is deprecated" - - it should "work with module IO" in { - val io = m.io.toTarget.toString - assert(io == s"$top>io") - } - - it should "not work for literals" in { - a[ChiselException] shouldBe thrownBy { - m.x.toTarget.toString - } - } - - it should "work with non-hardware values (but be deprecated)" in { - val (ylog, y) = grabLog(m.y.toTarget.toString) - val (zlog, z) = grabLog(m.z.toTarget.toString) - assert(y == s"$top>y") - ylog should include(deprecationMsg) - assert(z == s"$top>z") - zlog should include(deprecationMsg) - } - - it should "work with non-hardware bundle elements (but be deprecated)" in { - val (log, foo) = grabLog(m.z.foo.toTarget.toString) - log should include(deprecationMsg) - assert(foo == s"$top>z.foo") - } - - it should "work with modules" in { - val q = m.q.toTarget.toString - assert(q == s"~$mn|Queue") - } - - it should "warn on non-hardware types and provide information" in { - class Example extends Module { - val tpe = UInt(8.W) - - val in = IO(Input(tpe)) - val out = IO(Output(tpe)) - out := in - } - - var e: Example = null - chisel3.stage.ChiselStage.elaborate { e = new Example; e } - val (log, foo) = grabLog(e.tpe.toTarget) - log should include( - "Accessing the .instanceName or .toTarget of non-hardware Data is deprecated: 'tpe', in module 'Example'" - ) - } -} diff --git a/src/test/scala/chiselTests/TransitNameSpec.scala b/src/test/scala/chiselTests/TransitNameSpec.scala deleted file mode 100644 index ae08336d..00000000 --- a/src/test/scala/chiselTests/TransitNameSpec.scala +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -package chiselTests - -import chisel3._ -import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} -import chisel3.util.TransitName - -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers - -class TransitNameSpec extends AnyFlatSpec with Matchers { - - class MyModule extends RawModule { - val io = IO(new Bundle {}) - override val desiredName: String = "MyModule" - } - - /** A top-level module that instantiates three copies of MyModule */ - class Top extends RawModule { - - /* Assign the IO of a new MyModule instance to value "foo". The instance will be named "MyModule". */ - val foo = Module(new MyModule).io - - /* Assign the IO of a new MyModule instance to value "bar". The instance will be named "bar". */ - val bar = { - val x = Module(new MyModule) - TransitName(x.io, x) // TransitName returns the first argument - } - - /* Assign the IO of a new MyModule instance to value "baz". The instance will be named "baz_generated". */ - val baz = { - val x = Module(new MyModule) - TransitName.withSuffix("_generated")(x.io, x) // TransitName returns the first argument - } - - } - - it should "transit a name" in { - - val firrtl = (new ChiselStage) - .emitFirrtl(new Top, Array("--target-dir", "test_run_dir/TransitNameSpec")) - - info("""output FIRRTL includes "inst MyModule"""") - firrtl should include("inst MyModule of MyModule") - - info("""output FIRRTL includes "inst bar"""") - firrtl should include("inst bar of MyModule") - - info("""output FIRRTL includes "inst baz_generated"""") - firrtl should include("inst baz_generated of MyModule") - } - -} diff --git a/src/test/scala/chiselTests/UIntOps.scala b/src/test/scala/chiselTests/UIntOps.scala deleted file mode 100644 index 2f55da9a..00000000 --- a/src/test/scala/chiselTests/UIntOps.scala +++ /dev/null @@ -1,290 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import org.scalatest._ -import chisel3.stage.ChiselStage -import chisel3.testers.BasicTester -import chisel3.util._ -import org.scalacheck.Shrink -import org.scalatest.matchers.should.Matchers - -class UIntOps extends Module { - val io = IO(new Bundle { - val a = Input(UInt(32.W)) - val b = Input(UInt(32.W)) - val addout = Output(UInt(32.W)) - val subout = Output(UInt(32.W)) - val addampout = Output(UInt(33.W)) - val subampout = Output(UInt(33.W)) - val timesout = Output(UInt(32.W)) - val divout = Output(UInt(32.W)) - val modout = Output(UInt(32.W)) - val lshiftout = Output(UInt(32.W)) - val rshiftout = Output(UInt(32.W)) - val lrotateout = Output(UInt(32.W)) - val rrotateout = Output(UInt(32.W)) - val lessout = Output(Bool()) - val greatout = Output(Bool()) - val eqout = Output(Bool()) - val noteqout = Output(Bool()) - val lesseqout = Output(Bool()) - val greateqout = Output(Bool()) - }) - - dontTouch(io) - - val a = io.a - val b = io.b - - io.addout := a +% b - io.subout := a -% b - io.addampout := a +& b - io.subampout := a -& b - io.timesout := (a * b)(31, 0) - io.divout := a / Mux(b === 0.U, 1.U, b) - io.modout := a % b - io.lshiftout := (a << b(3, 0))(31, 0) - io.rshiftout := a >> b - io.lrotateout := a.rotateLeft(5) - io.rrotateout := a.rotateRight(5) - io.lessout := a < b - io.greatout := a > b - io.eqout := a === b - io.noteqout := (a =/= b) - io.lesseqout := a <= b - io.greateqout := a >= b -} - -// Note a and b need to be "safe" -class UIntOpsTester(a: Long, b: Long) extends BasicTester { - require(a >= 0 && b >= 0) - - val dut = Module(new UIntOps) - dut.io.a := a.asUInt(32.W) - dut.io.b := b.asUInt(32.W) - - assert(dut.io.addout === (a + b).U(32.W)) - assert(dut.io.subout === (a - b).S(32.W).asUInt) - assert(dut.io.addampout === (a + b).U(33.W)) - assert(dut.io.subampout === (a - b).S(33.W).asUInt) - assert(dut.io.timesout === (a * b).U(32.W)) - assert(dut.io.divout === (a / (b.max(1))).U(32.W)) - assert(dut.io.modout === (a % (b.max(1))).U(32.W)) - assert(dut.io.lshiftout === (a << (b % 16)).U(32.W)) - assert(dut.io.rshiftout === (a >> b).U(32.W)) - assert( - dut.io.lrotateout === s"h${Integer.rotateLeft(a.toInt, 5).toHexString}" - .U(32.W) - ) - assert( - dut.io.rrotateout === s"h${Integer.rotateRight(a.toInt, 5).toHexString}" - .U(32.W) - ) - assert(dut.io.lessout === (a < b).B) - assert(dut.io.greatout === (a > b).B) - assert(dut.io.eqout === (a == b).B) - assert(dut.io.noteqout === (a != b).B) - assert(dut.io.lesseqout === (a <= b).B) - assert(dut.io.greateqout === (a >= b).B) - - stop() -} - -class GoodBoolConversion extends Module { - val io = IO(new Bundle { - val u = Input(UInt(1.W)) - val b = Output(Bool()) - }) - io.b := io.u.asBool -} - -class BadBoolConversion extends Module { - val io = IO(new Bundle { - val u = Input(UInt(5.W)) - val b = Output(Bool()) - }) - io.b := io.u.asBool -} - -class NegativeShift(t: => Bits) extends Module { - val io = IO(new Bundle {}) - Reg(t) >> -1 -} - -class BasicRotate extends BasicTester { - val shiftAmount = random.LFSR(4) - val ctr = RegInit(0.U(4.W)) - - val rotL = 1.U(3.W).rotateLeft(shiftAmount) - val rotR = 1.U(3.W).rotateRight(shiftAmount) - - printf("Shift amount: %d rotateLeft:%b rotateRight:%b\n", shiftAmount, rotL, rotR) - - switch(shiftAmount % 3.U) { - is(0.U, 3.U) { - assert(rotL === "b001".U) - assert(rotR === "b001".U) - } - is(1.U) { - assert(rotL === "b010".U) - assert(rotR === "b100".U) - } - is(2.U) { - assert(rotL === "b100".U) - assert(rotR === "b010".U) - } - } - - ctr := ctr + 1.U - - when(ctr === 15.U) { - stop() - } -} - -/** rotating a w-bit word left by n should be equivalent to rotating it by w - n - * to the left - */ -class MatchedRotateLeftAndRight(w: Int = 13) extends BasicTester { - val initValue = BigInt(w, scala.util.Random) - println(s"Initial value: ${initValue.toString(2)}") - - val maxWidthBits = log2Ceil(w + 1) - val shiftAmount1 = RegInit(0.U(w.W)) - val shiftAmount2 = RegInit(w.U(w.W)) - shiftAmount1 := shiftAmount1 + 1.U - shiftAmount2 := shiftAmount2 - 1.U - - val value = RegInit(initValue.U(w.W)) - - val out1 = value.rotateLeft(shiftAmount1) - val out2 = value.rotateRight(shiftAmount2) - - printf("rotateLeft by %d: %b\n", shiftAmount1, out1) - - assert(out1 === out2) - when(shiftAmount1 === w.U) { - assert(out1 === initValue.U) - stop() - } -} - -class UIntLitExtractTester extends BasicTester { - assert("b101010".U.extract(2) === false.B) - assert("b101010".U.extract(3) === true.B) - assert("b101010".U.extract(100) === false.B) - assert("b101010".U(3, 0) === "b1010".U) - assert("b101010".U(9, 0) === "b0000101010".U) - - assert("b101010".U(6.W)(2) === false.B) - assert("b101010".U(6.W)(3) === true.B) - assert("b101010".U(6.W)(100) === false.B) - assert("b101010".U(6.W)(3, 0) === "b1010".U) - assert("b101010".U(6.W)(9, 0) === "b0000101010".U) - stop() -} - -class UIntOpsSpec extends ChiselPropSpec with Matchers with Utils { - // Disable shrinking on error. - implicit val noShrinkListVal = Shrink[List[Int]](_ => Stream.empty) - implicit val noShrinkInt = Shrink[Int](_ => Stream.empty) - - property("Bools can be created from 1 bit UInts") { - ChiselStage.elaborate(new GoodBoolConversion) - } - - property("Bools cannot be created from >1 bit UInts") { - a[Exception] should be thrownBy extractCause[Exception] { ChiselStage.elaborate(new BadBoolConversion) } - } - - property("Out-of-bounds extraction from known-width UInts") { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate(new RawModule { - val u = IO(Input(UInt(2.W))) - u(2, 1) - }) - } - } - - property("Out-of-bounds single-bit extraction from known-width UInts") { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate(new RawModule { - val u = IO(Input(UInt(2.W))) - u(2) - }) - } - } - - property("UIntOps should elaborate") { - ChiselStage.elaborate { new UIntOps } - } - - property("UIntOpsTester should return the correct result") { - assertTesterPasses { new UIntOpsTester(123, 7) } - } - - property("Negative shift amounts are invalid") { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate(new NegativeShift(UInt())) - } - } - - property("rotateLeft and rotateRight should work for dynamic shift values") { - assertTesterPasses(new BasicRotate) - } - - property( - "rotateLeft and rotateRight should be consistent for dynamic shift values" - ) { - assertTesterPasses(new MatchedRotateLeftAndRight) - } - - property("Bit extraction on literals should work for all non-negative indices") { - assertTesterPasses(new UIntLitExtractTester) - } - - property("asBools should support chained apply") { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val in = Input(UInt(8.W)) - val out = Output(Bool()) - }) - io.out := io.in.asBools()(2) - }) - } - - // We use WireDefault with 2 arguments because of - // https://www.chisel-lang.org/api/3.4.1/chisel3/WireDefault$.html - // Single Argument case 2 - property("modulo divide should give min width of arguments") { - assertKnownWidth(4) { - val x = WireDefault(UInt(8.W), DontCare) - val y = WireDefault(UInt(4.W), DontCare) - val op = x % y - WireDefault(chiselTypeOf(op), op) - } - assertKnownWidth(4) { - val x = WireDefault(UInt(4.W), DontCare) - val y = WireDefault(UInt(8.W), DontCare) - val op = x % y - WireDefault(chiselTypeOf(op), op) - } - } - - property("division should give the width of the numerator") { - assertKnownWidth(8) { - val x = WireDefault(UInt(8.W), DontCare) - val y = WireDefault(UInt(4.W), DontCare) - val op = x / y - WireDefault(chiselTypeOf(op), op) - } - assertKnownWidth(4) { - val x = WireDefault(UInt(4.W), DontCare) - val y = WireDefault(UInt(8.W), DontCare) - val op = x / y - WireDefault(chiselTypeOf(op), op) - } - } -} diff --git a/src/test/scala/chiselTests/Util.scala b/src/test/scala/chiselTests/Util.scala deleted file mode 100644 index d2f8bd9b..00000000 --- a/src/test/scala/chiselTests/Util.scala +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -// Useful utilities for tests - -package chiselTests - -import chisel3._ -import chisel3.experimental.Interval -import chisel3.internal.firrtl.{IntervalRange, KnownBinaryPoint, Width} -import _root_.firrtl.{ir => firrtlir} - -class PassthroughModuleIO extends Bundle { - val in = Input(UInt(32.W)) - val out = Output(UInt(32.W)) -} - -trait AbstractPassthroughModule extends RawModule { - val io = IO(new PassthroughModuleIO) - io.out := io.in -} - -class PassthroughModule extends Module with AbstractPassthroughModule -class PassthroughMultiIOModule extends Module with AbstractPassthroughModule -class PassthroughRawModule extends RawModule with AbstractPassthroughModule - -case class ScalaIntervalSimulator(intervalRange: IntervalRange) { - val binaryPoint: Int = intervalRange.binaryPoint.asInstanceOf[KnownBinaryPoint].value - val epsilon: Double = 1.0 / math.pow(2.0, binaryPoint.toDouble) - - val (lower, upper) = (intervalRange.lowerBound, intervalRange.upperBound) match { - - case (firrtlir.Closed(lower1), firrtlir.Closed(upper1)) => (lower1, upper1) - case (firrtlir.Closed(lower1), firrtlir.Open(upper1)) => (lower1, upper1 - epsilon) - case (firrtlir.Open(lower1), firrtlir.Closed(upper1)) => (lower1 + epsilon, upper1) - case (firrtlir.Open(lower1), firrtlir.Open(upper1)) => (lower1 + epsilon, upper1 - epsilon) - case _ => - throw new Exception(s"lower and upper bounds must be defined, range here is $intervalRange") - } - - def clip(value: BigDecimal): BigDecimal = { - - if (value < lower) { - lower - } else if (value > upper) { - upper - } else { - value - } - } - - def wrap(value: BigDecimal): BigDecimal = { - - if (value < lower) { - upper + (value - lower) + epsilon - } else if (value > upper) { - ((value - upper) - epsilon) + lower - } else { - value - } - } - - def allValues: Iterator[BigDecimal] = { - (lower to upper by epsilon).toIterator - } - - def makeLit(value: BigDecimal): Interval = { - Interval.fromDouble(value.toDouble, width = Width(), binaryPoint = binaryPoint.BP) - } -} diff --git a/src/test/scala/chiselTests/Vec.scala b/src/test/scala/chiselTests/Vec.scala deleted file mode 100644 index e46774dd..00000000 --- a/src/test/scala/chiselTests/Vec.scala +++ /dev/null @@ -1,542 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import org.scalacheck._ - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.testers.{BasicTester, TesterDriver} -import chisel3.util._ -import org.scalacheck.Shrink -import scala.annotation.tailrec - -class LitTesterMod(vecSize: Int) extends Module { - val io = IO(new Bundle { - val out = Output(Vec(vecSize, UInt())) - }) - io.out := VecInit(Seq.fill(vecSize) { 0.U }) -} - -class RegTesterMod(vecSize: Int) extends Module { - val io = IO(new Bundle { - val in = Input(Vec(vecSize, UInt())) - val out = Output(Vec(vecSize, UInt())) - }) - val vecReg = RegNext(io.in, VecInit(Seq.fill(vecSize) { 0.U })) - io.out := vecReg -} - -class IOTesterMod(vecSize: Int) extends Module { - val io = IO(new Bundle { - val in = Input(Vec(vecSize, UInt())) - val out = Output(Vec(vecSize, UInt())) - }) - io.out := io.in -} - -class OneBitUnitRegVec extends Module { - val io = IO(new Bundle { - val out = Output(UInt(1.W)) - }) - val oneBitUnitRegVec = Reg(Vec(1, UInt(1.W))) - oneBitUnitRegVec(0) := 1.U(1.W) - io.out := oneBitUnitRegVec(0) -} - -class LitTester(w: Int, values: List[Int]) extends BasicTester { - val dut = Module(new LitTesterMod(values.length)) - for (a <- dut.io.out) - assert(a === 0.U) - stop() -} - -class RegTester(w: Int, values: List[Int]) extends BasicTester { - val v = VecInit(values.map(_.U(w.W))) - val dut = Module(new RegTesterMod(values.length)) - val doneReg = RegInit(false.B) - dut.io.in := v - when(doneReg) { - for ((a, b) <- dut.io.out.zip(values)) - assert(a === b.U) - stop() - }.otherwise { - doneReg := true.B - for (a <- dut.io.out) - assert(a === 0.U) - } -} - -class IOTester(w: Int, values: List[Int]) extends BasicTester { - val v = VecInit(values.map(_.U(w.W))) // Does this need a Wire? No. It's a Vec of Lits and hence synthesizeable. - val dut = Module(new IOTesterMod(values.length)) - dut.io.in := v - for ((a, b) <- dut.io.out.zip(values)) { - assert(a === b.U) - } - stop() -} - -class IOTesterModFill(vecSize: Int) extends Module { - // This should generate a BindingException when we attempt to wire up the Vec.fill elements - // since they're pure types and hence unsynthesizeable. - val io = IO(new Bundle { - val in = Input(VecInit(Seq.fill(vecSize) { UInt() })) - val out = Output(VecInit(Seq.fill(vecSize) { UInt() })) - }) - io.out := io.in -} - -class ValueTester(w: Int, values: List[Int]) extends BasicTester { - val v = VecInit(values.map(_.asUInt(w.W))) - for ((a, b) <- v.zip(values)) { - assert(a === b.asUInt) - } - stop() -} - -class TabulateTester(n: Int) extends BasicTester { - val v = VecInit(Range(0, n).map(i => (i * 2).asUInt)) - val x = VecInit(Array.tabulate(n) { i => (i * 2).asUInt }) - val u = VecInit.tabulate(n)(i => (i * 2).asUInt) - - assert(v.asUInt() === x.asUInt()) - assert(v.asUInt() === u.asUInt()) - assert(x.asUInt() === u.asUInt()) - - stop() -} - -class FillTester(n: Int, value: Int) extends BasicTester { - val x = VecInit(Array.fill(n)(value.U)) - val u = VecInit.fill(n)(value.U) - - assert(x.asUInt() === u.asUInt(), cf"Expected Vec to be filled like $x, instead VecInit.fill created $u") - stop() -} - -object VecMultiDimTester { - - @tailrec - private def assert2DIsCorrect(n: Int, arr: Vec[Vec[UInt]], compArr: Seq[Seq[Int]]): Unit = { - val compareRow = arr(n).zip(compArr(n)) - compareRow.foreach(x => assert(x._1 === x._2.U)) - if (n != 0) assert2DIsCorrect(n - 1, arr, compArr) - } - - @tailrec - private def assert3DIsCorrect(n: Int, m: Int, arr: Vec[Vec[Vec[UInt]]], compArr: Seq[Seq[Seq[Int]]]): Unit = { - assert2DIsCorrect(m - 1, arr(n), compArr(n)) - if (n != 0) assert3DIsCorrect(n - 1, m, arr, compArr) - } - - class TabulateTester2D(n: Int, m: Int) extends BasicTester { - def gen(x: Int, y: Int): UInt = (x + y).asUInt - def genCompVec(x: Int, y: Int): Int = x + y - val vec = VecInit.tabulate(n, m) { gen } - val compArr = Seq.tabulate(n, m) { genCompVec } - - assert2DIsCorrect(n - 1, vec, compArr) - stop() - } - - class TabulateTester3D(n: Int, m: Int, p: Int) extends BasicTester { - def gen(x: Int, y: Int, z: Int): UInt = (x + y + z).asUInt - def genCompVec(x: Int, y: Int, z: Int): Int = x + y + z - val vec = VecInit.tabulate(n, m, p) { gen } - val compArr = Seq.tabulate(n, m, p) { genCompVec } - - assert3DIsCorrect(n - 1, m, vec, compArr) - stop() - } - - class Fill2DTester(n: Int, m: Int, value: Int) extends BasicTester { - val u = VecInit.fill(n, m)(value.U) - val compareArr = Seq.fill(n, m)(value) - - assert2DIsCorrect(n - 1, u, compareArr) - stop() - } - - class Fill3DTester(n: Int, m: Int, p: Int, value: Int) extends BasicTester { - val u = VecInit.fill(n, m, p)(value.U) - val compareArr = Seq.fill(n, m, p)(value) - - assert3DIsCorrect(n - 1, m, u, compareArr) - stop() - } - - class BidirectionalTester2DFill(n: Int, m: Int) extends BasicTester { - val mod = Module(new PassthroughModule) - val vec2D = VecInit.fill(n, m)(mod.io) - for { - vec1D <- vec2D - module <- vec1D - } yield { - module <> Module(new PassthroughModuleTester).io - } - stop() - } - - class BidirectionalTester3DFill(n: Int, m: Int, p: Int) extends BasicTester { - val mod = Module(new PassthroughModule) - val vec3D = VecInit.fill(n, m, p)(mod.io) - - for { - vec2D <- vec3D - vec1D <- vec2D - module <- vec1D - } yield { - module <> (Module(new PassthroughModuleTester).io) - } - stop() - } - - class TabulateModuleTester(value: Int) extends Module { - val io = IO(Flipped(new PassthroughModuleIO)) - // This drives the input of a PassthroughModule - io.in := value.U - } - - class BidirectionalTester2DTabulate(n: Int, m: Int) extends BasicTester { - val vec2D = VecInit.tabulate(n, m) { (x, y) => Module(new TabulateModuleTester(x + y + 1)).io } - - for { - x <- 0 until n - y <- 0 until m - } yield { - val value = x + y + 1 - val receiveMod = Module(new PassthroughModule).io - vec2D(x)(y) <> receiveMod - assert(receiveMod.out === value.U) - } - stop() - } - - class BidirectionalTester3DTabulate(n: Int, m: Int, p: Int) extends BasicTester { - val vec3D = VecInit.tabulate(n, m, p) { (x, y, z) => Module(new TabulateModuleTester(x + y + z + 1)).io } - - for { - x <- 0 until n - y <- 0 until m - z <- 0 until p - } yield { - val value = x + y + z + 1 - val receiveMod = Module(new PassthroughModule).io - vec3D(x)(y)(z) <> receiveMod - assert(receiveMod.out === value.U) - } - stop() - } -} - -class IterateTester(start: Int, len: Int)(f: UInt => UInt) extends BasicTester { - val controlVec = VecInit(Seq.iterate(start.U, len)(f)) - val testVec = VecInit.iterate(start.U, len)(f) - assert( - controlVec.asUInt() === testVec.asUInt(), - cf"Expected Vec to be filled like $controlVec, instead created $testVec\n" - ) - stop() -} - -class ShiftRegisterTester(n: Int) extends BasicTester { - val (cnt, wrap) = Counter(true.B, n * 2) - val shifter = Reg(Vec(n, UInt((log2Ceil(n).max(1)).W))) - (shifter, shifter.drop(1)).zipped.foreach(_ := _) - shifter(n - 1) := cnt - when(cnt >= n.asUInt) { - val expected = cnt - n.asUInt - assert(shifter(0) === expected) - } - when(wrap) { - stop() - } -} - -class HugeVecTester(n: Int) extends BasicTester { - require(n > 0) - val myVec = Wire(Vec(n, UInt())) - myVec.foreach { x => - x := 123.U - assert(x === 123.U) - } - stop() -} - -class OneBitUnitRegVecTester extends BasicTester { - val dut = Module(new OneBitUnitRegVec) - assert(dut.io.out === 1.U) - stop() -} - -class ZeroEntryVecTester extends BasicTester { - require(Vec(0, Bool()).getWidth == 0) - - val bundleWithZeroEntryVec = new Bundle { - val foo = Bool() - val bar = Vec(0, Bool()) - } - require(0.U.asTypeOf(bundleWithZeroEntryVec).getWidth == 1) - require(bundleWithZeroEntryVec.asUInt.getWidth == 1) - - val m = Module(new Module { - val io = IO(Output(bundleWithZeroEntryVec)) - io.foo := false.B - }) - WireDefault(m.io.bar) - - stop() -} - -class PassthroughModuleTester extends Module { - val io = IO(Flipped(new PassthroughModuleIO)) - // This drives the input of a PassthroughModule - io.in := 123.U - assert(io.out === 123.U) -} - -class ModuleIODynamicIndexTester(n: Int) extends BasicTester { - val duts = VecInit.fill(n)(Module(new PassthroughModule).io) - val tester = Module(new PassthroughModuleTester) - - val (cycle, done) = Counter(true.B, n) - for ((m, i) <- duts.zipWithIndex) { - when(cycle =/= i.U) { - m.in := 0.U // default - assert(m.out === 0.U) - }.otherwise { - m.in := DontCare - } - } - // only connect one dut per cycle - duts(cycle) <> tester.io - assert(duts(cycle).out === 123.U) - - when(done) { stop() } -} - -class ReduceTreeTester() extends BasicTester { - 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) - } - - class Foo[T <: Data](n: Int, private val gen: T) extends Module { - val io = IO(new FooIO(n, gen)) - - def foo(a: DecoupledIO[T], b: DecoupledIO[T]) = { - a.ready := true.B - b.ready := true.B - val out = Wire(new DecoupledIO(gen)) - - out.valid := true.B - - val regSel = RegInit(false.B) - out.bits := Mux(regSel, a.bits, b.bits) - out.ready := a.ready - out - } - - io.out <> io.in.reduceTree(foo) - } - - val dut = Module(new Foo(5, UInt(5.W))) - dut.io := DontCare - stop() -} - -class VecSpec extends ChiselPropSpec with Utils { - // Disable shrinking on error. - implicit val noShrinkListVal = Shrink[List[Int]](_ => Stream.empty) - implicit val noShrinkInt = Shrink[Int](_ => Stream.empty) - - property("Vecs should be assignable") { - forAll(safeUIntN(8)) { - case (w: Int, v: List[Int]) => - assertTesterPasses { new ValueTester(w, v) } - } - } - - property("Vecs should be passed through vec IO") { - forAll(safeUIntN(8)) { - case (w: Int, v: List[Int]) => - assertTesterPasses { new IOTester(w, v) } - } - } - - property("Vec.fill with a pure type should generate an exception") { - // We don't really need a sequence of random widths here, since any should throw an exception. - forAll(safeUIntWidth) { - case (w: Int) => - an[BindingException] should be thrownBy extractCause[BindingException] { - ChiselStage.elaborate(new IOTesterModFill(w)) - } - } - } - - property("A Reg of a Vec should operate correctly") { - forAll(safeUIntN(8)) { - case (w: Int, v: List[Int]) => - assertTesterPasses { new RegTester(w, v) } - } - } - - property("A Vec of lit should operate correctly") { - forAll(safeUIntN(8)) { - case (w: Int, v: List[Int]) => - assertTesterPasses { new LitTester(w, v) } - } - } - - property("VecInit should tabulate correctly") { - forAll(smallPosInts) { (n: Int) => assertTesterPasses { new TabulateTester(n) } } - } - - property("VecInit should tabulate 2D vec correctly") { - forAll(smallPosInts, smallPosInts) { (n: Int, m: Int) => - assertTesterPasses { new VecMultiDimTester.TabulateTester2D(n, m) } - } - } - - property("VecInit should tabulate 3D vec correctly") { - forAll(smallPosInts, smallPosInts, smallPosInts) { (n: Int, m: Int, p: Int) => - assertTesterPasses { new VecMultiDimTester.TabulateTester3D(n, m, p) } - } - } - - property("VecInit should fill correctly") { - forAll(smallPosInts, Gen.choose(0, 50)) { (n: Int, value: Int) => assertTesterPasses { new FillTester(n, value) } } - } - - property("VecInit should fill 2D vec correctly") { - forAll(smallPosInts, smallPosInts, Gen.choose(0, 50)) { (n: Int, m: Int, value: Int) => - assertTesterPasses { new VecMultiDimTester.Fill2DTester(n, m, value) } - } - } - - property("VecInit should fill 3D vec correctly") { - forAll(smallPosInts, smallPosInts, smallPosInts, Gen.choose(0, 50)) { (n: Int, m: Int, p: Int, value: Int) => - assertTesterPasses { new VecMultiDimTester.Fill3DTester(n, m, p, value) } - } - } - - property("VecInit should support 2D fill bidirectional wire connection") { - forAll(smallPosInts, smallPosInts) { (n: Int, m: Int) => - assertTesterPasses { new VecMultiDimTester.BidirectionalTester2DFill(n, m) } - } - } - - property("VecInit should support 3D fill bidirectional wire connection") { - forAll(smallPosInts, smallPosInts, smallPosInts) { (n: Int, m: Int, p: Int) => - assertTesterPasses { new VecMultiDimTester.BidirectionalTester3DFill(n, m, p) } - } - } - - property("VecInit should support 2D tabulate bidirectional wire connection") { - forAll(smallPosInts, smallPosInts) { (n: Int, m: Int) => - assertTesterPasses { new VecMultiDimTester.BidirectionalTester2DTabulate(n, m) } - } - } - - property("VecInit should support 3D tabulate bidirectional wire connection") { - forAll(smallPosInts, smallPosInts, smallPosInts) { (n: Int, m: Int, p: Int) => - assertTesterPasses { new VecMultiDimTester.BidirectionalTester3DTabulate(n, m, p) } - } - } - - property("VecInit should iterate correctly") { - forAll(Gen.choose(1, 10), smallPosInts) { (start: Int, len: Int) => - assertTesterPasses { new IterateTester(start, len)(x => x + 50.U) } - } - } - - property("Regs of vecs should be usable as shift registers") { - forAll(smallPosInts) { (n: Int) => assertTesterPasses { new ShiftRegisterTester(n) } } - } - - property("Infering widths on huge Vecs should not cause a stack overflow") { - assertTesterPasses(new HugeVecTester(10000), annotations = TesterDriver.verilatorOnly) - } - - property("A Reg of a Vec of a single 1 bit element should compile and work") { - assertTesterPasses { new OneBitUnitRegVecTester } - } - - property("A Vec with zero entries should compile and have zero width") { - assertTesterPasses { new ZeroEntryVecTester } - } - - property("Dynamic indexing of a Vec of Module IOs should work") { - assertTesterPasses { new ModuleIODynamicIndexTester(4) } - } - - property("It should be possible to bulk connect a Vec and a Seq") { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val out = Output(Vec(4, UInt(8.W))) - }) - val seq = Seq.fill(4)(0.U) - io.out <> seq - }) - } - - property("Bulk connecting a Vec and Seq of different sizes should report a ChiselException") { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val out = Output(Vec(4, UInt(8.W))) - }) - val seq = Seq.fill(5)(0.U) - io.out <> seq - }) - } - } - - property("It should be possible to initialize a Vec with DontCare") { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val out = Output(Vec(4, UInt(8.W))) - }) - io.out := VecInit(Seq(4.U, 5.U, DontCare, 2.U)) - }) - } - - property("Indexing a Chisel type Vec by a hardware type should give a sane error message") { - a[ExpectedHardwareException] should be thrownBy extractCause[ChiselException] { - ChiselStage.elaborate { - new Module { - val io = IO(new Bundle {}) - val foo = Vec(2, Bool()) - foo(0.U) := false.B - } - } - } - } - - property("reduceTree should preserve input/output type") { - assertTesterPasses { new ReduceTreeTester() } - } - - property("Vecs of empty Bundles and empty Records should work") { - class MyModule(gen: Record) extends Module { - val idx = IO(Input(UInt(2.W))) - val in = IO(Input(gen)) - val out = IO(Output(gen)) - - val reg = RegInit(0.U.asTypeOf(Vec(4, gen))) - reg(idx) := in - out := reg(idx) - } - class EmptyBundle extends Bundle - class EmptyRecord extends Record { - val elements = collection.immutable.ListMap.empty - override def cloneType = (new EmptyRecord).asInstanceOf[this.type] - } - for (gen <- List(new EmptyBundle, new EmptyRecord)) { - val chirrtl = ChiselStage.emitChirrtl(new MyModule(gen)) - chirrtl should include("input in : { }") - chirrtl should include("reg reg : { }[4]") - } - } -} diff --git a/src/test/scala/chiselTests/VecLiteralSpec.scala b/src/test/scala/chiselTests/VecLiteralSpec.scala deleted file mode 100644 index dcc96b17..00000000 --- a/src/test/scala/chiselTests/VecLiteralSpec.scala +++ /dev/null @@ -1,529 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.experimental.BundleLiterals.AddBundleLiteralConstructor -import chisel3.experimental.VecLiterals._ -import chisel3.experimental.{FixedPoint, VecLiteralException} -import chisel3.stage.ChiselStage -import chisel3.testers.BasicTester -import chisel3.util.Counter -import scala.language.reflectiveCalls - -class VecLiteralSpec extends ChiselFreeSpec with Utils { - object MyEnum extends ChiselEnum { - val sA, sB, sC = Value - } - object MyEnumB extends ChiselEnum { - val sA, sB = Value - } - - "Vec literals should work with chisel Enums" in { - val enumVec = Vec(3, MyEnum()).Lit(0 -> MyEnum.sA, 1 -> MyEnum.sB, 2 -> MyEnum.sC) - enumVec(0).toString should include(MyEnum.sA.toString) - enumVec(1).toString should include(MyEnum.sB.toString) - enumVec(2).toString should include(MyEnum.sC.toString) - } - - "improperly constructed vec literals should be detected" - { - "indices in vec literal muse be greater than zero and less than length" in { - val e = intercept[VecLiteralException] { - Vec(2, UInt(4.W)).Lit(0 -> 1.U, 1 -> 2.U, 2 -> 3.U, 3 -> 4.U, -2 -> 7.U) - } - e.getMessage should include( - "VecLiteral: The following indices (2,3,-2) are less than zero or greater or equal to than Vec length" - ) - } - - "indices in vec literals must not be repeated" in { - val e = intercept[VecLiteralException] { - Vec(2, UInt(4.W)).Lit(0 -> 1.U, 1 -> 2.U, 2 -> 3.U, 2 -> 3.U, 2 -> 3.U, 3 -> 4.U) - } - e.getMessage should include("VecLiteral: has duplicated indices 2(3 times)") - } - "lits must fit in vec element width" in { - val e = intercept[VecLiteralException] { - Vec(2, SInt(4.W)).Lit(0 -> 0xab.S, 1 -> 0xbc.S) - } - e.getMessage should include( - "VecLiteral: Vec[SInt<4>] has the following incorrectly typed or sized initializers: " + - "0 -> SInt<9>(171),1 -> SInt<9>(188)" - ) - } - - "all lits must be the same type but width can be equal or smaller than the Vec's element width" in { - val v = Vec(2, SInt(4.W)).Lit(0 -> 1.S, 1 -> -2.S) - v(0).toString should include(1.S(4.W).toString) - v(1).toString should include((-2).S(4.W).toString) - v.toString should include("SInt<4>[2](0=SLit(1,<4>), 1=SLit(-2,<4>)") - } - - "all lits must be the same type but width cannot be greater than Vec's element width" in { - val e = intercept[VecLiteralException] { - val v = Vec(2, SInt(4.W)).Lit(0 -> 11.S, 1 -> -0xffff.S) - } - e.getMessage should include( - "VecLiteral: Vec[SInt<4>] has the following incorrectly typed or sized initializers: 0 -> SInt<5>(11),1 -> SInt<17>(-65535)" - ) - } - } - - //NOTE: I had problems where this would not work if this class declaration was inside test scope - class HasVecInit extends Module { - val initValue = Vec(4, UInt(8.W)).Lit(0 -> 0xab.U(8.W), 1 -> 0xcd.U(8.W), 2 -> 0xef.U(8.W), 3 -> 0xff.U(8.W)) - val y = RegInit(initValue) - } - - "Vec literals should work when used to initialize a reg of vec" in { - val firrtl = (new ChiselStage).emitFirrtl(new HasVecInit, args = Array("--full-stacktrace")) - firrtl should include("""_y_WIRE[0] <= UInt<8>("hab")""") - firrtl should include("""_y_WIRE[1] <= UInt<8>("hcd")""") - firrtl should include("""_y_WIRE[2] <= UInt<8>("hef")""") - firrtl should include("""_y_WIRE[3] <= UInt<8>("hff")""") - firrtl should include(""" reset => (reset, _y_WIRE)""".stripMargin) - } - - //NOTE: I had problems where this would not work if this class declaration was inside test scope - class HasPartialVecInit extends Module { - val initValue = Vec(4, UInt(8.W)).Lit(0 -> 0xab.U(8.W), 2 -> 0xef.U(8.W), 3 -> 0xff.U(8.W)) - val y = RegInit(initValue) - } - - "Vec literals should work when used to partially initialize a reg of vec" in { - val firrtl = (new ChiselStage).emitFirrtl(new HasPartialVecInit, args = Array("--full-stacktrace")) - firrtl should include("""_y_WIRE[0] <= UInt<8>("hab")""") - firrtl should include("""_y_WIRE[1] is invalid""") - firrtl should include("""_y_WIRE[2] <= UInt<8>("hef")""") - firrtl should include("""_y_WIRE[3] <= UInt<8>("hff")""") - firrtl should include(""" reset => (reset, _y_WIRE)""".stripMargin) - } - - class ResetRegWithPartialVecLiteral extends Module { - val in = IO(Input(Vec(4, UInt(8.W)))) - val out = IO(Output(Vec(4, UInt(8.W)))) - val initValue = Vec(4, UInt(8.W)).Lit(0 -> 0xab.U(8.W), 2 -> 0xef.U(8.W), 3 -> 0xff.U(8.W)) - val y = RegInit(initValue) - when(in(1) > 0.U) { - y(1) := in(1) - } - when(in(2) > 0.U) { - y(2) := in(2) - } - out := y - } - - "Vec literals should only init specified fields when used to partially initialize a reg of vec" in { - println(ChiselStage.emitFirrtl(new ResetRegWithPartialVecLiteral)) - assertTesterPasses(new BasicTester { - val m = Module(new ResetRegWithPartialVecLiteral) - val (counter, wrapped) = Counter(true.B, 8) - m.in := DontCare - when(counter < 2.U) { - m.in(1) := 0xff.U - m.in(2) := 0xff.U - }.elsewhen(counter === 2.U) { - chisel3.assert(m.out(1) === 0xff.U) - chisel3.assert(m.out(2) === 0xff.U) - }.elsewhen(counter === 3.U) { - m.in(1) := 0.U - m.in(2) := 0.U - m.reset := true.B - }.elsewhen(counter > 2.U) { - // m.out(1) should not be reset, m.out(2) should be reset - chisel3.assert(m.out(1) === 0xff.U) - chisel3.assert(m.out(2) === 0xef.U) - } - when(wrapped) { - stop() - } - }) - } - - "lowest of vec literal contains least significant bits and " in { - val y = Vec(4, UInt(8.W)).Lit(0 -> 0xab.U(8.W), 1 -> 0xcd.U(8.W), 2 -> 0xef.U(8.W), 3 -> 0xff.U(8.W)) - y.litValue should be(BigInt("FFEFCDAB", 16)) - } - - "the order lits are specified does not matter" in { - val y = Vec(4, UInt(8.W)).Lit(3 -> 0xff.U(8.W), 2 -> 0xef.U(8.W), 1 -> 0xcd.U(8.W), 0 -> 0xab.U(8.W)) - y.litValue should be(BigInt("FFEFCDAB", 16)) - } - - "regardless of the literals widths, packing should be done based on the width of the Vec's gen" in { - val z = Vec(4, UInt(8.W)).Lit(0 -> 0x2.U, 1 -> 0x2.U, 2 -> 0x2.U, 3 -> 0x3.U) - z.litValue should be(BigInt("03020202", 16)) - } - - "packing sparse vec lits should not pack, litOption returns None" in { - // missing sub-listeral for index 2 - val z = Vec(4, UInt(8.W)).Lit(0 -> 0x2.U, 1 -> 0x2.U, 3 -> 0x3.U) - - z.litOption should be(None) - } - - "registers can be initialized with a Vec literal" in { - assertTesterPasses(new BasicTester { - val y = RegInit(Vec(4, UInt(8.W)).Lit(0 -> 0xab.U(8.W), 1 -> 0xcd.U(8.W), 2 -> 0xef.U(8.W), 3 -> 0xff.U(8.W))) - chisel3.assert(y.asUInt === BigInt("FFEFCDAB", 16).U) - stop() - }) - } - - "how does asUInt work" in { - assertTesterPasses(new BasicTester { - val vec1 = Vec(4, UInt(16.W)).Lit(0 -> 0xdd.U, 1 -> 0xcc.U, 2 -> 0xbb.U, 3 -> 0xaa.U) - - val vec2 = VecInit(Seq(0xdd.U, 0xcc.U, 0xbb.U, 0xaa.U)) - printf("vec1 %x\n", vec1.asUInt()) - printf("vec2 %x\n", vec2.asUInt()) - stop() - }) - } - - "Vec literals uint conversion" in { - class M1 extends Module { - val out1 = IO(Output(UInt(64.W))) - val out2 = IO(Output(UInt(64.W))) - - val v1 = Vec(4, UInt(16.W)).Lit(0 -> 0xdd.U, 1 -> 0xcc.U, 2 -> 0xbb.U, 3 -> 0xaa.U) - out1 := v1.asUInt - - val v2 = VecInit(0xdd.U(16.W), 0xcc.U, 0xbb.U, 0xaa.U) - out2 := v2.asUInt - } - - assertTesterPasses(new BasicTester { - val m = Module(new M1) - chisel3.assert(m.out1 === m.out2) - stop() - }) - } - - "VecLits should work properly with .asUInt" in { - val outsideVecLit = Vec(4, UInt(16.W)).Lit(0 -> 0xdd.U, 1 -> 0xcc.U, 2 -> 0xbb.U, 3 -> 0xaa.U) - - assertTesterPasses { - new BasicTester { - chisel3.assert(outsideVecLit(0) === 0xdd.U, "v(0)") - stop() - } - } - } - - "bundle literals should work in RTL" in { - val outsideVecLit = Vec(4, UInt(16.W)).Lit(0 -> 0xdd.U, 1 -> 0xcc.U, 2 -> 0xbb.U, 3 -> 0xaa.U) - - assertTesterPasses { - new BasicTester { - chisel3.assert(outsideVecLit(0) === 0xdd.U, "v(0)") - chisel3.assert(outsideVecLit(1) === 0xcc.U) - chisel3.assert(outsideVecLit(2) === 0xbb.U) - chisel3.assert(outsideVecLit(3) === 0xaa.U) - - chisel3.assert(outsideVecLit.litValue.U === outsideVecLit.asUInt()) - - val insideVecLit = Vec(4, UInt(16.W)).Lit(0 -> 0xdd.U, 1 -> 0xcc.U, 2 -> 0xbb.U, 3 -> 0xaa.U) - chisel3.assert(insideVecLit(0) === 0xdd.U) - chisel3.assert(insideVecLit(1) === 0xcc.U) - chisel3.assert(insideVecLit(2) === 0xbb.U) - chisel3.assert(insideVecLit(3) === 0xaa.U) - - chisel3.assert(insideVecLit(0) === outsideVecLit(0)) - chisel3.assert(insideVecLit(1) === outsideVecLit(1)) - chisel3.assert(insideVecLit(2) === outsideVecLit(2)) - chisel3.assert(insideVecLit(3) === outsideVecLit(3)) - - val vecWire1 = Wire(Vec(4, UInt(16.W))) - vecWire1 := outsideVecLit - - chisel3.assert(vecWire1(0) === 0xdd.U) - chisel3.assert(vecWire1(1) === 0xcc.U) - chisel3.assert(vecWire1(2) === 0xbb.U) - chisel3.assert(vecWire1(3) === 0xaa.U) - - val vecWire2 = Wire(Vec(4, UInt(16.W))) - vecWire2 := insideVecLit - - chisel3.assert(vecWire2(0) === 0xdd.U) - chisel3.assert(vecWire2(1) === 0xcc.U) - chisel3.assert(vecWire2(2) === 0xbb.U) - chisel3.assert(vecWire2(3) === 0xaa.U) - - stop() - } - } - } - - "partial vec literals should work in RTL" in { - assertTesterPasses { - new BasicTester { - val vecLit = Vec(4, UInt(8.W)).Lit(0 -> 42.U, 2 -> 5.U) - chisel3.assert(vecLit(0) === 42.U) - chisel3.assert(vecLit(2) === 5.U) - - val vecWire = Wire(Vec(4, UInt(8.W))) - vecWire := vecLit - - chisel3.assert(vecWire(0) === 42.U) - chisel3.assert(vecWire(2) === 5.U) - - stop() - } - } - } - - "nested vec literals should be constructable" in { - val outerVec = Vec(2, Vec(3, UInt(4.W))).Lit( - 0 -> Vec(3, UInt(4.W)).Lit(0 -> 1.U, 1 -> 2.U, 2 -> 3.U), - 1 -> Vec(3, UInt(4.W)).Lit(0 -> 4.U, 1 -> 5.U, 2 -> 6.U) - ) - - outerVec.litValue should be(BigInt("654321", 16)) - outerVec(0).litValue should be(BigInt("321", 16)) - outerVec(1).litValue should be(BigInt("654", 16)) - outerVec(0)(0).litValue should be(BigInt(1)) - outerVec(0)(1).litValue should be(BigInt(2)) - outerVec(0)(2).litValue should be(BigInt(3)) - outerVec(1)(0).litValue should be(BigInt(4)) - outerVec(1)(1).litValue should be(BigInt(5)) - outerVec(1)(2).litValue should be(BigInt(6)) - } - - "contained vecs should work" in { - assertTesterPasses { - new BasicTester { - val outerVec = Vec(2, Vec(3, UInt(4.W))).Lit( - 0 -> Vec(3, UInt(4.W)).Lit(0 -> 1.U, 1 -> 2.U, 2 -> 3.U), - 1 -> Vec(3, UInt(4.W)).Lit(0 -> 4.U, 1 -> 5.U, 2 -> 6.U) - ) - - chisel3.assert(outerVec(0)(0) === 1.U) - chisel3.assert(outerVec(0)(1) === 2.U) - chisel3.assert(outerVec(0)(2) === 3.U) - chisel3.assert(outerVec(1)(0) === 4.U) - chisel3.assert(outerVec(1)(1) === 5.U) - chisel3.assert(outerVec(1)(2) === 6.U) - - val v0 = outerVec(0) - val v1 = outerVec(1) - chisel3.assert(v0(0) === 1.U) - chisel3.assert(v0(1) === 2.U) - chisel3.assert(v0(2) === 3.U) - chisel3.assert(v1(0) === 4.U) - chisel3.assert(v1(1) === 5.U) - chisel3.assert(v1(2) === 6.U) - - stop() - } - } - } - - //TODO: decide what behavior here should be - "This doesn't work should it" ignore { - assertTesterPasses { - new BasicTester { - def vecFactory = Vec(2, FixedPoint(8.W, 4.BP)) - - val vecWire1 = Wire(Output(vecFactory)) - val vecLit1 = vecFactory.Lit(0 -> (1.5).F(8.W, 4.BP)) - val vecLit2 = vecFactory.Lit(1 -> (3.25).F(8.W, 4.BP)) - - vecWire1 := vecLit1 - vecWire1 := vecLit2 - printf("vw1(0) %x vw1(1) %x\n", vecWire1(0).asUInt(), vecWire1(1).asUInt()) - chisel3.assert(vecWire1(0) === (1.5).F(8.W, 4.BP)) - chisel3.assert(vecWire1(1) === (3.25).F(8.W, 4.BP)) - stop() - } - } - } - - "partially initialized Vec literals should assign" in { - assertTesterPasses { - new BasicTester { - def vecFactory = Vec(2, FixedPoint(8.W, 4.BP)) - - val vecWire1 = Wire(Output(vecFactory)) - val vecWire2 = Wire(Output(vecFactory)) - val vecLit1 = vecFactory.Lit(0 -> (1.5).F(8.W, 4.BP)) - val vecLit2 = vecFactory.Lit(1 -> (3.25).F(8.W, 4.BP)) - - vecWire1 := vecLit1 - vecWire2 := vecLit2 - vecWire1(1) := (0.5).F(8.W, 4.BP) - printf("vw1(0) %x vw1(1) %x\n", vecWire1(0).asUInt(), vecWire1(1).asUInt()) - chisel3.assert(vecWire1(0) === (1.5).F(8.W, 4.BP)) - chisel3.assert(vecWire1(1) === (0.5).F(8.W, 4.BP)) // Last connect won - chisel3.assert(vecWire2(1) === (3.25).F(8.W, 4.BP)) - stop() - } - } - } - - "Vec literals should work as register reset values" in { - assertTesterPasses { - new BasicTester { - val r = RegInit(Vec(3, UInt(11.W)).Lit(0 -> 0xa.U, 1 -> 0xb.U, 2 -> 0xc.U)) - r := (r.asUInt + 1.U).asTypeOf(Vec(3, UInt(11.W))) // prevent constprop - - // check reset values on first cycle out of reset - chisel3.assert(r(0) === 0xa.U) - chisel3.assert(r(1) === 0xb.U) - chisel3.assert(r(2) === 0xc.U) - stop() - } - } - } - - "partially initialized Vec literals should work as register reset values" in { - assertTesterPasses { - new BasicTester { - val r = RegInit(Vec(3, UInt(11.W)).Lit(0 -> 0xa.U, 2 -> 0xc.U)) - r := (r.asUInt + 1.U).asTypeOf(Vec(3, UInt(11.W))) // prevent constprop - // check reset values on first cycle out of reset - chisel3.assert(r(0) === 0xa.U) - chisel3.assert(r(2) === 0xc.U) - stop() - } - } - } - - "Fields extracted from Vec Literals should work as register reset values" in { - assertTesterPasses { - new BasicTester { - val r = RegInit(Vec(3, UInt(11.W)).Lit(0 -> 0xa.U, 2 -> 0xc.U).apply(0)) - r := r + 1.U // prevent const prop - chisel3.assert(r === 0xa.U) // coming out of reset - stop() - } - } - } - - "DontCare fields extracted from Vec Literals should work as register reset values" in { - assertTesterPasses { - new BasicTester { - val r = RegInit(Vec(3, Bool()).Lit(0 -> true.B).apply(2)) - r := reset.asBool - printf(p"r = $r\n") // Can't assert because reset value is DontCare - stop() - } - } - } - - "DontCare fields extracted from Vec Literals should work in other Expressions" in { - assertTesterPasses { - new BasicTester { - val x = Vec(3, Bool()).Lit(0 -> true.B).apply(2) || true.B - chisel3.assert(x === true.B) - stop() - } - } - } - - "vec literals with non-literal values should fail" in { - val exc = intercept[VecLiteralException] { - extractCause[VecLiteralException] { - ChiselStage.elaborate { - new RawModule { - (Vec(3, UInt(11.W)).Lit(0 -> UInt())) - } - } - } - } - exc.getMessage should include("field 0 specified with non-literal value UInt") - } - - "vec literals are instantiated on connect and are not bulk connected" in { - class VecExample5 extends RawModule { - val out = IO(Output(Vec(2, UInt(4.W)))) - val bundle = Vec(2, UInt(4.W)).Lit( - 0 -> 0xa.U, - 1 -> 0xb.U - ) - out := bundle - } - - val firrtl = (new chisel3.stage.ChiselStage).emitFirrtl(new VecExample5, args = Array("--full-stacktrace")) - firrtl should include("""out[0] <= UInt<4>("ha")""") - firrtl should include("""out[1] <= UInt<4>("hb")""") - } - - class SubBundle extends Bundle { - val foo = UInt(8.W) - val bar = UInt(4.W) - } - - class VecExample extends RawModule { - val out = IO(Output(Vec(2, new SubBundle))) - val bundle = Vec(2, new SubBundle).Lit( - 0 -> (new SubBundle).Lit(_.foo -> 42.U, _.bar -> 22.U), - 1 -> (new SubBundle).Lit(_.foo -> 7.U, _.bar -> 3.U) - ) - out := bundle - } - - "vec literals can contain bundles and should not be bulk connected" in { - val chirrtl = (new chisel3.stage.ChiselStage).emitChirrtl(new VecExample, args = Array("--full-stacktrace")) - chirrtl should include("""out[0].bar <= UInt<5>("h16")""") - chirrtl should include("""out[0].foo <= UInt<6>("h2a")""") - chirrtl should include("""out[1].bar <= UInt<2>("h3")""") - chirrtl should include("""out[1].foo <= UInt<3>("h7")""") - } - - "vec literals can have bundle children" in { - val vec = Vec(2, new SubBundle).Lit( - 0 -> (new SubBundle).Lit(_.foo -> 0xab.U, _.bar -> 0xc.U), - 1 -> (new SubBundle).Lit(_.foo -> 0xde.U, _.bar -> 0xf.U) - ) - vec.litValue.toString(16) should be("defabc") - } - - "vec literals can have bundle children assembled incrementally" in { - val bundle1 = (new SubBundle).Lit(_.foo -> 0xab.U, _.bar -> 0xc.U) - val bundle2 = (new SubBundle).Lit(_.foo -> 0xde.U, _.bar -> 0xf.U) - - bundle1.litValue.toString(16) should be("abc") - bundle2.litValue.toString(16) should be("def") - - val vec = Vec(2, new SubBundle).Lit(0 -> bundle1, 1 -> bundle2) - - vec.litValue.toString(16) should be("defabc") - } - - "bundles can contain vec lits" in { - val vec1 = Vec(3, UInt(4.W)).Lit(0 -> 0xa.U, 1 -> 0xb.U, 2 -> 0xc.U) - val vec2 = Vec(2, UInt(4.W)).Lit(0 -> 0xd.U, 1 -> 0xe.U) - val bundle = (new Bundle { - val foo = Vec(3, UInt(4.W)) - val bar = Vec(2, UInt(4.W)) - }).Lit(_.foo -> vec1, _.bar -> vec2) - bundle.litValue.toString(16) should be("cbaed") - } - - "bundles can contain vec lits in-line" in { - val bundle = (new Bundle { - val foo = Vec(3, UInt(4.W)) - val bar = Vec(2, UInt(4.W)) - }).Lit( - _.foo -> Vec(3, UInt(4.W)).Lit(0 -> 0xa.U, 1 -> 0xb.U, 2 -> 0xc.U), - _.bar -> Vec(2, UInt(4.W)).Lit(0 -> 0xd.U, 1 -> 0xe.U) - ) - bundle.litValue.toString(16) should be("cbaed") - } - - "Vec.Lit is a trivial Vec literal factory" in { - val vec = Vec.Lit(0xa.U, 0xb.U) - vec(0).litValue should be(0xa) - vec(1).litValue should be(0xb) - } - - "Vec.Lit bases it's element width on the widest literal supplied" in { - val vec = Vec.Lit(0xa.U, 0xbbbb.U) - vec(0).litValue should be(0xa) - vec(1).litValue should be(0xbbbb) - vec.length should be(2) - vec.getWidth should be(16 * 2) - vec.litValue should be(BigInt("bbbb000a", 16)) - } -} diff --git a/src/test/scala/chiselTests/VecToTargetSpec.scala b/src/test/scala/chiselTests/VecToTargetSpec.scala deleted file mode 100644 index 20c6f306..00000000 --- a/src/test/scala/chiselTests/VecToTargetSpec.scala +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage - -trait VecToTargetSpecUtils extends Utils { - this: ChiselFunSpec => - - class Foo extends RawModule { - val vec = IO(Input(Vec(4, Bool()))) - - // Index a Vec with a Scala literal. - val scalaLit = 0 - val vecSubaccessScalaLit = vec(scalaLit) - - // Index a Vec with a Chisel literal. - val chiselLit = 0.U - val vecSubaccessChiselLit = vec(chiselLit) - - // Index a Vec with a node. - val node = IO(Input(UInt(2.W))) - val vecSubaccessNode = vec(node) - - // Put an otherwise un-targetable Vec subaccess into a temp. - val vecSubaccessTmp = WireInit(vecSubaccessNode) - } - - val expectedError = "You cannot target Vec subaccess:" - - def conversionSucceeds(data: InstanceId) = { - describe(".toTarget") { - it("should convert successfully") { - data.toTarget - } - } - - describe(".toNamed") { - it("should convert successfully") { - data.toNamed - } - } - } - - def conversionFails(data: InstanceId) = { - describe(".toTarget") { - it("should fail to convert with a useful error message") { - (the[ChiselException] thrownBy extractCause[ChiselException] { - data.toTarget - }).getMessage should include(expectedError) - } - } - - describe(".toNamed") { - it("should fail to convert with a useful error message") { - (the[ChiselException] thrownBy extractCause[ChiselException] { - data.toNamed - }).getMessage should include(expectedError) - } - } - } -} - -class VecToTargetSpec extends ChiselFunSpec with VecToTargetSpecUtils { - describe("Vec subaccess") { - var foo: Foo = null - ChiselStage.elaborate { foo = new Foo; foo } - - describe("with a Scala literal") { - (it should behave).like(conversionSucceeds(foo.vecSubaccessScalaLit)) - } - - describe("with a Chisel literal") { - (it should behave).like(conversionFails(foo.vecSubaccessChiselLit)) - } - - describe("with a Node") { - (it should behave).like(conversionFails(foo.vecSubaccessNode)) - } - - describe("with an un-targetable construct that is assigned to a temporary") { - (it should behave).like(conversionSucceeds(foo.vecSubaccessTmp)) - } - } -} diff --git a/src/test/scala/chiselTests/VectorPacketIO.scala b/src/test/scala/chiselTests/VectorPacketIO.scala deleted file mode 100644 index 1474177f..00000000 --- a/src/test/scala/chiselTests/VectorPacketIO.scala +++ /dev/null @@ -1,71 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.testers.BasicTester -import chisel3.util._ - -/** - * This test used to fail when assignment statements were - * contained in DeqIO and EnqIO constructors. - * The symptom is creation of a firrtl file - * with missing declarations, the problem is exposed by - * the creation of the val outs in VectorPacketIO - * - * NOTE: The problem does not exist now because the initialization - * code has been removed from DeqIO and EnqIO - * - * IMPORTANT: The canonical way to initialize a decoupled inteface is still being debated. - */ -class Packet extends Bundle { - val header = UInt(1.W) -} - -/** - * The problem occurs with just the ins or the outs - * lines also. - * The problem does not occur if the Vec is taken out - */ -class VectorPacketIO(val n: Int) extends Bundle { - val ins = Vec(n, chisel3.util.DeqIO(new Packet())) - val outs = Vec(n, chisel3.util.EnqIO(new Packet())) -} - -/** - * a module uses the vector based IO bundle - * the value of n does not affect the error - */ -class BrokenVectorPacketModule extends Module { - val n = 4 - val io = IO(new VectorPacketIO(n)) - - // Avoid a "Reference io is not fully initialized" error from firrtl. - for (i <- 0 until n) { - io.outs(i) <> io.ins(i) - } - - /* the following method of initializing the circuit may change in the future */ - io.ins.foreach(_.nodeq()) - io.outs.foreach(_.noenq()) -} - -class VectorPacketIOUnitTester extends BasicTester { - val dut = Module(new BrokenVectorPacketModule) - dut.io <> DontCare - - // This counter just makes the test end quicker - val c = Counter(1) - when(c.inc()) { - stop() - } -} - -class VectorPacketIOUnitTesterSpec extends ChiselFlatSpec { - "a circuit using an io containing a vector of EnqIO wrapped packets" should - "compile and run" in { - assertTesterPasses { - new VectorPacketIOUnitTester - } - } -} diff --git a/src/test/scala/chiselTests/VerificationSpec.scala b/src/test/scala/chiselTests/VerificationSpec.scala deleted file mode 100644 index 32cee9e3..00000000 --- a/src/test/scala/chiselTests/VerificationSpec.scala +++ /dev/null @@ -1,156 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.experimental.{ChiselAnnotation, verification => formal} -import chisel3.stage.ChiselStage -import firrtl.annotations.{ReferenceTarget, SingleTargetAnnotation} -import org.scalatest.matchers.should.Matchers - -import java.io.File - -class SimpleTest extends Module { - val io = IO(new Bundle { - val in = Input(UInt(8.W)) - val out = Output(UInt(8.W)) - }) - io.out := io.in - cover(io.in === 3.U) - when(io.in === 3.U) { - assume(io.in =/= 2.U) - assert(io.out === io.in) - } -} - -/** Dummy verification annotation. - * @param target target of component to be annotated - */ -case class VerifAnnotation(target: ReferenceTarget) extends SingleTargetAnnotation[ReferenceTarget] { - def duplicate(n: ReferenceTarget): VerifAnnotation = this.copy(target = n) -} - -object VerifAnnotation { - - /** Create annotation for a given verification component. - * @param c component to be annotated - */ - def annotate(c: VerificationStatement): Unit = { - chisel3.experimental.annotate(new ChiselAnnotation { - def toFirrtl: VerifAnnotation = VerifAnnotation(c.toTarget) - }) - } -} - -class VerificationSpec extends ChiselPropSpec with Matchers { - - def assertContains(s: Seq[String], x: String): Unit = { - val containsLine = s.map(_.contains(x)).reduce(_ || _) - assert(containsLine, s"\n $x\nwas not found in`\n ${s.mkString("\n ")}``") - } - - property("basic equality check should work") { - val fir = ChiselStage.emitChirrtl(new SimpleTest) - val lines = fir.split("\n").map(_.trim) - - // reset guard around the verification statement - assertContains(lines, "when _T_2 : @[VerificationSpec.scala") - assertContains(lines, "cover(clock, _T, UInt<1>(\"h1\"), \"\")") - - assertContains(lines, "when _T_6 : @[VerificationSpec.scala") - assertContains(lines, "assume(clock, _T_4, UInt<1>(\"h1\"), \"\")") - - assertContains(lines, "when _T_10 : @[VerificationSpec.scala") - assertContains(lines, "assert(clock, _T_8, UInt<1>(\"h1\"), \"\")") - } - - property("annotation of verification constructs should work") { - - /** Circuit that contains and annotates verification nodes. */ - class AnnotationTest extends Module { - val io = IO(new Bundle { - val in = Input(UInt(8.W)) - val out = Output(UInt(8.W)) - }) - io.out := io.in - val cov = cover(io.in === 3.U) - val assm = chisel3.assume(io.in =/= 2.U) - val asst = chisel3.assert(io.out === io.in) - VerifAnnotation.annotate(cov) - VerifAnnotation.annotate(assm) - VerifAnnotation.annotate(asst) - } - - // compile circuit - val testDir = new File("test_run_dir", "VerificationAnnotationTests") - (new ChiselStage).emitSystemVerilog( - gen = new AnnotationTest, - args = Array("-td", testDir.getPath) - ) - - // read in annotation file - val annoFile = new File(testDir, "AnnotationTest.anno.json") - annoFile should exist - val annoLines = scala.io.Source.fromFile(annoFile).getLines.toList - - // check for expected verification annotations - exactly(3, annoLines) should include("chiselTests.VerifAnnotation") - exactly(1, annoLines) should include("~AnnotationTest|AnnotationTest>asst") - exactly(1, annoLines) should include("~AnnotationTest|AnnotationTest>assm") - exactly(1, annoLines) should include("~AnnotationTest|AnnotationTest>cov") - - // read in FIRRTL file - val firFile = new File(testDir, "AnnotationTest.fir") - firFile should exist - val firLines = scala.io.Source.fromFile(firFile).getLines.toList - - // check that verification components have expected names - (exactly(1, firLines) should include).regex("^\\s*cover\\(.*\\) : cov") - (exactly(1, firLines) should include).regex("^\\s*assume\\(.*\\) : assm") - (exactly(1, firLines) should include).regex("^\\s*assert\\(.*\\) : asst") - } - - property("annotation of verification constructs with suggested name should work") { - - /** Circuit that annotates a renamed verification nodes. */ - class AnnotationRenameTest extends Module { - val io = IO(new Bundle { - val in = Input(UInt(8.W)) - val out = Output(UInt(8.W)) - }) - io.out := io.in - - val goodbye = chisel3.assert(io.in === 1.U) - goodbye.suggestName("hello") - VerifAnnotation.annotate(goodbye) - - VerifAnnotation.annotate(chisel3.assume(io.in =/= 2.U).suggestName("howdy")) - } - - // compile circuit - val testDir = new File("test_run_dir", "VerificationAnnotationRenameTests") - (new ChiselStage).emitSystemVerilog( - gen = new AnnotationRenameTest, - args = Array("-td", testDir.getPath) - ) - - // read in annotation file - val annoFile = new File(testDir, "AnnotationRenameTest.anno.json") - annoFile should exist - val annoLines = scala.io.Source.fromFile(annoFile).getLines.toList - - // check for expected verification annotations - exactly(2, annoLines) should include("chiselTests.VerifAnnotation") - exactly(1, annoLines) should include("~AnnotationRenameTest|AnnotationRenameTest>hello") - exactly(1, annoLines) should include("~AnnotationRenameTest|AnnotationRenameTest>howdy") - - // read in FIRRTL file - val firFile = new File(testDir, "AnnotationRenameTest.fir") - firFile should exist - val firLines = scala.io.Source.fromFile(firFile).getLines.toList - - // check that verification components have expected names - (exactly(1, firLines) should include).regex("^\\s*assert\\(.*\\) : hello") - (exactly(1, firLines) should include).regex("^\\s*assume\\(.*\\) : howdy") - } -} diff --git a/src/test/scala/chiselTests/WarningSpec.scala b/src/test/scala/chiselTests/WarningSpec.scala deleted file mode 100644 index 1bb9e6dc..00000000 --- a/src/test/scala/chiselTests/WarningSpec.scala +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.util._ -import chisel3.stage.ChiselStage - -class WarningSpec extends ChiselFlatSpec with Utils { - behavior.of("Warnings") - - object MyEnum extends ChiselEnum { - val e0, e1, e2 = Value - } - - class MyModule extends Module { - val in = IO(Input(UInt(2.W))) - val out1 = IO(Output(MyEnum())) - val out2 = IO(Output(MyEnum())) - def func(out: EnumType): Unit = { - out := MyEnum(in) - } - func(out1) - func(out2) - } - - "Warnings" should "be de-duplicated" in { - val (log, _) = grabLog(ChiselStage.elaborate(new MyModule)) - def countSubstring(s: String, sub: String) = - s.sliding(sub.length).count(_ == sub) - countSubstring(log, "Casting non-literal UInt") should be(1) - } - - "Warnings" should "be treated as errors with warningsAsErrors" in { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - val args = Array("--warnings-as-errors") - (new ChiselStage).emitChirrtl(new MyModule, args) - } - } -} diff --git a/src/test/scala/chiselTests/When.scala b/src/test/scala/chiselTests/When.scala deleted file mode 100644 index 032a8eac..00000000 --- a/src/test/scala/chiselTests/When.scala +++ /dev/null @@ -1,168 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.testers.BasicTester -import chisel3.util._ - -class WhenTester() extends BasicTester { - val cnt = Counter(4) - when(true.B) { cnt.inc() } - - val out = Wire(UInt(3.W)) - when(cnt.value === 0.U) { - out := 1.U - }.elsewhen(cnt.value === 1.U) { - out := 2.U - }.elsewhen(cnt.value === 2.U) { - out := 3.U - }.otherwise { - out := 0.U - } - - assert(out === cnt.value + 1.U) - - when(cnt.value === 3.U) { - stop() - } -} - -class OverlappedWhenTester() extends BasicTester { - val cnt = Counter(4) - when(true.B) { cnt.inc() } - - val out = Wire(UInt(3.W)) - when(cnt.value <= 0.U) { - out := 1.U - }.elsewhen(cnt.value <= 1.U) { - out := 2.U - }.elsewhen(cnt.value <= 2.U) { - out := 3.U - }.otherwise { - out := 0.U - } - - assert(out === cnt.value + 1.U) - - when(cnt.value === 3.U) { - stop() - } -} - -class NoOtherwiseOverlappedWhenTester() extends BasicTester { - val cnt = Counter(4) - when(true.B) { cnt.inc() } - - val out = Wire(UInt(3.W)) - when(cnt.value <= 0.U) { - out := 1.U - }.elsewhen(cnt.value <= 1.U) { - out := 2.U - }.elsewhen(cnt.value <= 2.U) { - out := 3.U - }.elsewhen(cnt.value <= 3.U) { - out := 0.U - }.otherwise { - out := DontCare - } - - assert(out === cnt.value + 1.U) - - when(cnt.value === 3.U) { - stop() - } -} - -class SubmoduleWhenTester extends BasicTester { - val (cycle, done) = Counter(true.B, 3) - when(done) { stop() } - val children = - Seq(Module(new PassthroughModule), Module(new PassthroughMultiIOModule), Module(new PassthroughRawModule)) - children.foreach { child => - when(cycle === 1.U) { - child.io.in := "hdeadbeef".U - assert(child.io.out === "hdeadbeef".U) - }.otherwise { - child.io.in := "h0badcad0".U - assert(child.io.out === "h0badcad0".U) - } - } -} - -class WhenCondTester extends BasicTester { - val pred = Wire(Vec(4, Bool())) - val (cycle, done) = Counter(true.B, 1 << pred.size) - // Cycle through every predicate - pred := cycle.asBools - val Seq(a, b, c, d) = pred // Just for nicer accessors - // When want the when predicates on connection to optimize away, - // it's not necessary but it makes the Verilog prettier - val w1, w2, w3, w4, w5, w6, w7 = WireInit(Bool(), DontCare) - when(a) { - w1 := when.cond - when(b) { - w2 := when.cond - }.elsewhen(c) { - w3 := when.cond - }.elsewhen(d) { - w4 := when.cond - }.otherwise { - w5 := when.cond - } - }.otherwise { - w6 := when.cond - } - w7 := when.cond - - assert(w1 === a) - assert(w2 === (a && b)) - assert(w3 === (a && !b && c)) - assert(w4 === (a && !b && !c && d)) - assert(w5 === (a && !b && !c && !d)) - assert(w6 === !a) - assert(w7) - - when(done) { stop() } -} - -class WhenSpec extends ChiselFlatSpec with Utils { - "When, elsewhen, and otherwise with orthogonal conditions" should "work" in { - assertTesterPasses { new WhenTester } - } - "When, elsewhen, and otherwise with overlapped conditions" should "work" in { - assertTesterPasses { new OverlappedWhenTester } - } - "When and elsewhen without otherwise with overlapped conditions" should "work" in { - assertTesterPasses { new NoOtherwiseOverlappedWhenTester } - } - "Conditional connections to submodule ports" should "be handled properly" in { - assertTesterPasses(new SubmoduleWhenTester) - } - "when.cond" should "give the current when condition" in { - assertTesterPasses(new WhenCondTester) - } - - "Returning in a when scope" should "give a reasonable error message" in { - val e = the[ChiselException] thrownBy extractCause[ChiselException] { - ChiselStage.elaborate(new Module { - val io = IO(new Bundle { - val foo = Input(UInt(8.W)) - val bar = Input(UInt(8.W)) - val cond = Input(Bool()) - val out = Output(UInt(8.W)) - }) - def func(): UInt = { - when(io.cond) { - // This is bad, do not do this!!! - return io.foo - } - return io.bar - } - io.out := func() - }) - } - e.getMessage should include("Cannot exit from a when() block with a \"return\"") - } -} diff --git a/src/test/scala/chiselTests/WidthSpec.scala b/src/test/scala/chiselTests/WidthSpec.scala deleted file mode 100644 index 77a09e1c..00000000 --- a/src/test/scala/chiselTests/WidthSpec.scala +++ /dev/null @@ -1,250 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ - -class SimpleBundle extends Bundle { - val x = UInt(4.W) - val y = UInt() -} -object SimpleBundle { - def intoWire(): SimpleBundle = { - val w = Wire(new SimpleBundle) - w.x := 0.U(4.W) - w.y := 0.U(4.W) - w - } -} - -class WidthSpec extends ChiselFlatSpec { - "Literals without specified widths" should "get the minimum legal width" in { - "hdeadbeef".U.getWidth should be(32) - "h_dead_beef".U.getWidth should be(32) - "h0a".U.getWidth should be(4) - "h1a".U.getWidth should be(5) - "h0".U.getWidth should be(1) - 1.U.getWidth should be(1) - 1.S.getWidth should be(2) - } -} - -abstract class WireRegWidthSpecImpl extends ChiselFlatSpec { - def name: String - def builder[T <: Data](x: T): T - - behavior.of(name) - - it should "set the width if the template type has a set width" in { - assertKnownWidth(4) { - builder(UInt(4.W)) - } - assertKnownWidth(4) { - val w = builder(new SimpleBundle) - w := SimpleBundle.intoWire() - w.x - } - assertKnownWidth(4) { - val x = builder(Vec(1, UInt(4.W))) - x(0) - } - } - - it should "infer the width if the template type has no width" in { - assertInferredWidth(4) { - val w = builder(UInt()) - w := 0.U(4.W) - w - } - assertInferredWidth(4) { - val w = builder(new SimpleBundle) - w := SimpleBundle.intoWire() - w.y - } - assertInferredWidth(4) { - val w = builder(Vec(1, UInt())) - w(0) := 0.U(4.W) - w(0) - } - } -} - -class WireWidthSpec extends WireRegWidthSpecImpl { - def name: String = "Wire" - def builder[T <: Data](x: T): T = Wire(x) -} -class RegWidthSpec extends WireRegWidthSpecImpl { - def name: String = "Reg" - def builder[T <: Data](x: T): T = Reg(x) -} - -abstract class WireDefaultRegInitSpecImpl extends ChiselFlatSpec { - def name: String - def builder1[T <: Data](x: T): T - def builder2[T <: Data](x: T, y: T): T - - behavior.of(s"$name (Single Argument)") - - it should "set width if passed a literal with forced width" in { - assertKnownWidth(4) { - builder1(3.U(4.W)) - } - } - - it should "NOT set width if passed a literal without a forced width" in { - assertInferredWidth(4) { - val w = builder1(3.U) - w := 3.U(4.W) - w - } - } - - it should "NOT set width if passed a non-literal" in { - assertInferredWidth(4) { - val w = WireDefault(3.U(4.W)) - builder1(w) - } - } - - it should "copy the widths of aggregates" in { - assertInferredWidth(4) { - val w = builder1(SimpleBundle.intoWire()) - w.y - } - assertKnownWidth(4) { - val w = builder1(SimpleBundle.intoWire()) - w.x - } - assertInferredWidth(4) { - val x = Wire(Vec(1, UInt())) - x(0) := 0.U(4.W) - val w = builder1(x) - w(0) - } - assertKnownWidth(4) { - val x = Wire(Vec(1, UInt(4.W))) - x(0) := 0.U(4.W) - val w = builder1(x) - w(0) - } - } - - behavior.of(s"$name (Double Argument)") - - it should "set the width if the template type has a set width" in { - assertKnownWidth(4) { - WireDefault(UInt(4.W), 0.U) - } - assertKnownWidth(4) { - WireDefault(UInt(4.W), 0.U(2.W)) - } - assertKnownWidth(4) { - val w = WireDefault(new SimpleBundle, SimpleBundle.intoWire()) - w.x - } - assertKnownWidth(4) { - val x = Wire(Vec(1, UInt())) - x(0) := 0.U(4.W) - val w = WireDefault(Vec(1, UInt(4.W)), x) - w(0) - } - } - - it should "infer the width if the template type has no width" in { - val templates = Seq( - () => 0.U, - () => 0.U(2.W), - () => WireDefault(0.U), - () => WireDefault(0.U(2.W)) - ) - for (gen <- templates) { - assertInferredWidth(4) { - val w = WireDefault(UInt(), gen()) - w := 0.U(4.W) - w - } - } - assertInferredWidth(4) { - val w = WireDefault(new SimpleBundle, SimpleBundle.intoWire()) - w.y - } - assertInferredWidth(4) { - val x = Wire(Vec(1, UInt())) - x(0) := 0.U(4.W) - val w = WireDefault(Vec(1, UInt()), x) - w(0) - } - } -} - -class WireDefaultWidthSpec extends WireDefaultRegInitSpecImpl { - def name: String = "WireDefault" - def builder1[T <: Data](x: T): T = WireDefault(x) - def builder2[T <: Data](x: T, y: T): T = WireDefault(x, y) -} - -class RegInitWidthSpec extends WireDefaultRegInitSpecImpl { - def name: String = "RegInit" - def builder1[T <: Data](x: T): T = RegInit(x) - def builder2[T <: Data](x: T, y: T): T = RegInit(x, y) -} - -class OpWidthSpec extends ChiselFlatSpec { - import firrtl._ - import firrtl.ir._ - - val maxWidth = 5 - val uIntOps: Seq[((UInt, UInt) => UInt, PrimOp)] = - Seq( - (_ +& _, PrimOps.Add), - (_ -& _, PrimOps.Sub), - (_ * _, PrimOps.Mul), - (_ / _, PrimOps.Div), - (_ % _, PrimOps.Rem), - (_ << _, PrimOps.Dshl), - (_ >> _, PrimOps.Dshr) - ) - - assertTesterPasses(new chisel3.testers.BasicTester { - for (i <- 0 to maxWidth) { - for (j <- 0 to maxWidth) { - for ((cOp, fOp) <- uIntOps) { - val args = Seq(i, j).map(w => Reference("", UIntType(IntWidth(w)))) - fOp.propagateType(DoPrim(fOp, args, Nil, UnknownType)) match { - case UIntType(IntWidth(w)) => - val x = 0.U(maxWidth.W).head(i) - val y = 0.U(maxWidth.W).head(j) - assert(w == cOp(x, y).getWidth) - } - } - } - } - stop() - }) - - val sIntOps: Seq[((SInt, SInt) => SInt, PrimOp)] = - Seq( - (_ +& _, PrimOps.Add), - (_ -& _, PrimOps.Sub), - (_ * _, PrimOps.Mul), - (_ / _, PrimOps.Div), - (_ % _, PrimOps.Rem) - ) - - assertTesterPasses(new chisel3.testers.BasicTester { - for (i <- 0 to maxWidth) { - for (j <- 0 to maxWidth) { - for ((cOp, fOp) <- sIntOps) { - val args = Seq(i, j).map(w => Reference("", SIntType(IntWidth(w)))) - fOp.propagateType(DoPrim(fOp, args, Nil, UnknownType)) match { - case SIntType(IntWidth(w)) => - val x = 0.U(maxWidth.W).head(i).asSInt - val y = 0.U(maxWidth.W).head(j).asSInt - assert(w == cOp(x, y).getWidth) - } - } - } - } - stop() - }) -} diff --git a/src/test/scala/chiselTests/WireSpec.scala b/src/test/scala/chiselTests/WireSpec.scala deleted file mode 100644 index 058a7f08..00000000 --- a/src/test/scala/chiselTests/WireSpec.scala +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.stage.ChiselStage - -class WireSpec extends ChiselFlatSpec { - "WireDefault.apply" should "work" in { - assertCompiles("WireDefault(UInt(4.W), 2.U)") - } - it should "allow DontCare" in { - assertCompiles("WireDefault(UInt(4.W), DontCare)") - } - it should "not allow DontCare to affect type inference" in { - assertCompiles("val x: UInt = WireDefault(UInt(4.W), DontCare)") - } - it should "not allow init argument to affect type inference" in { - assertDoesNotCompile("val x: UInt = WireDefault(UInt(4.W), 2.S)") - } - it should "have source locator information on wires" in { - class Dummy extends chisel3.Module { - val in = IO(Input(Bool())) - val out = IO(Output(Bool())) - - val wire = WireInit(Bool(), true.B) - val wire2 = Wire(Bool()) - wire2 := in - out := in & wire & wire2 - } - - val chirrtl = ChiselStage.emitChirrtl(new Dummy) - chirrtl should include("wire wire : UInt<1> @[WireSpec.scala") - chirrtl should include("wire wire2 : UInt<1> @[WireSpec.scala") - } -} diff --git a/src/test/scala/chiselTests/aop/InjectionSpec.scala b/src/test/scala/chiselTests/aop/InjectionSpec.scala deleted file mode 100644 index 1b69efa3..00000000 --- a/src/test/scala/chiselTests/aop/InjectionSpec.scala +++ /dev/null @@ -1,180 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.aop - -import chisel3.testers.{BasicTester, TesterDriver} -import chiselTests.{ChiselFlatSpec, Utils} -import chisel3._ -import chisel3.aop.Select -import chisel3.aop.injecting.InjectingAspect -import logger.{LogLevel, LogLevelAnnotation} - -object InjectionHierarchy { - - class SubmoduleManipulationTester extends BasicTester { - val moduleSubmoduleA = Module(new SubmoduleA) - } - - class MultiModuleInjectionTester extends BasicTester { - val subA0 = Module(new SubmoduleA) - val subA1 = Module(new SubmoduleA) - } - - class SubmoduleA extends Module { - val io = IO(new Bundle { - val out = Output(Bool()) - }) - io.out := false.B - } - - class SubmoduleB extends Module { - val io = IO(new Bundle { - val in = Input(Bool()) - }) - } - - class SubmoduleC extends experimental.ExtModule with util.HasExtModuleInline { - val io = IO(new Bundle { - val in = Input(Bool()) - }) - //scalastyle:off regex - setInline( - "SubmoduleC.v", - s""" - |module SubmoduleC( - | input io_in - |); - |endmodule - """.stripMargin - ) - } - - class AspectTester(results: Seq[Int]) extends BasicTester { - val values = VecInit(results.map(_.U)) - val counter = RegInit(0.U(results.length.W)) - counter := counter + 1.U - when(counter >= values.length.U) { - stop() - }.otherwise { - when(reset.asBool() === false.B) { - assert(counter === values(counter)) - } - } - } -} - -class InjectionSpec extends ChiselFlatSpec with Utils { - import InjectionHierarchy._ - val correctValueAspect = InjectingAspect( - { dut: AspectTester => Seq(dut) }, - { dut: AspectTester => - for (i <- 0 until dut.values.length) { - dut.values(i) := i.U - } - } - ) - - val wrongValueAspect = InjectingAspect( - { dut: AspectTester => Seq(dut) }, - { dut: AspectTester => - for (i <- 0 until dut.values.length) { - dut.values(i) := (i + 1).U - } - } - ) - - val manipulateSubmoduleAspect = InjectingAspect( - { dut: SubmoduleManipulationTester => Seq(dut) }, - { dut: SubmoduleManipulationTester => - val moduleSubmoduleB = Module(new SubmoduleB) - moduleSubmoduleB.io.in := dut.moduleSubmoduleA.io.out - //if we're here then we've elaborated correctly - stop() - } - ) - - val duplicateSubmoduleAspect = InjectingAspect( - { dut: SubmoduleManipulationTester => Seq(dut) }, - { _: SubmoduleManipulationTester => - // By creating a second SubmoduleA, the module names would conflict unless they were uniquified - val moduleSubmoduleA2 = Module(new SubmoduleA) - //if we're here then we've elaborated correctly - stop() - } - ) - - val addingExternalModules = InjectingAspect( - { dut: SubmoduleManipulationTester => Seq(dut) }, - { _: SubmoduleManipulationTester => - // By creating a second SubmoduleA, the module names would conflict unless they were uniquified - val moduleSubmoduleC = Module(new SubmoduleC) - moduleSubmoduleC.io <> DontCare - //if we're here then we've elaborated correctly - stop() - } - ) - - val multiModuleInjectionAspect = InjectingAspect( - { top: MultiModuleInjectionTester => - Select.collectDeep(top) { case m: SubmoduleA => m } - }, - { m: Module => - val wire = Wire(Bool()) - wire := m.reset.asBool() - dontTouch(wire) - stop() - } - ) - - "Test" should "pass if inserted the correct values" in { - assertTesterPasses { new AspectTester(Seq(0, 1, 2)) } - } - "Test" should "fail if inserted the wrong values" in { - assertTesterFails { new AspectTester(Seq(9, 9, 9)) } - } - "Test" should "pass if pass wrong values, but correct with aspect" in { - assertTesterPasses({ new AspectTester(Seq(9, 9, 9)) }, Nil, Seq(correctValueAspect) ++ TesterDriver.verilatorOnly) - } - "Test" should "pass if pass wrong values, then wrong aspect, then correct aspect" in { - assertTesterPasses( - new AspectTester(Seq(9, 9, 9)), - Nil, - Seq(wrongValueAspect, correctValueAspect) ++ TesterDriver.verilatorOnly - ) - } - "Test" should "fail if pass wrong values, then correct aspect, then wrong aspect" in { - assertTesterFails({ new AspectTester(Seq(9, 9, 9)) }, Nil, Seq(correctValueAspect, wrongValueAspect)) - } - - "Test" should "pass if the submodules in SubmoduleManipulationTester can be manipulated by manipulateSubmoduleAspect" in { - assertTesterPasses( - { new SubmoduleManipulationTester }, - Nil, - Seq(manipulateSubmoduleAspect) ++ TesterDriver.verilatorOnly - ) - } - - "Module name collisions when adding a new module" should "be resolved" in { - assertTesterPasses( - { new SubmoduleManipulationTester }, - Nil, - Seq(duplicateSubmoduleAspect) ++ TesterDriver.verilatorOnly - ) - } - - "Adding external modules" should "work" in { - assertTesterPasses( - { new SubmoduleManipulationTester }, - Nil, - Seq(addingExternalModules) ++ TesterDriver.verilatorOnly - ) - } - - "Injection into multiple submodules of the same class" should "work" in { - assertTesterPasses( - { new MultiModuleInjectionTester }, - Nil, - Seq(multiModuleInjectionAspect) ++ TesterDriver.verilatorOnly - ) - } -} diff --git a/src/test/scala/chiselTests/aop/SelectSpec.scala b/src/test/scala/chiselTests/aop/SelectSpec.scala deleted file mode 100644 index 72802c80..00000000 --- a/src/test/scala/chiselTests/aop/SelectSpec.scala +++ /dev/null @@ -1,230 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.aop - -import chisel3.testers.BasicTester -import chiselTests.ChiselFlatSpec -import chisel3._ -import chisel3.aop.Select.{PredicatedConnect, When, WhenNot} -import chisel3.aop.{Aspect, Select} -import chisel3.experimental.ExtModule -import chisel3.stage.{ChiselGeneratorAnnotation, DesignAnnotation} -import firrtl.AnnotationSeq - -import scala.reflect.runtime.universe.TypeTag - -class SelectTester(results: Seq[Int]) extends BasicTester { - val values = VecInit(results.map(_.U)) - val counter = RegInit(0.U(results.length.W)) - val added = counter + 1.U - counter := added - val overflow = counter >= values.length.U - val nreset = reset.asBool() === false.B - val selected = values(counter) - val zero = 0.U + 0.U - var p: printf.Printf = null - when(overflow) { - counter := zero - stop() - }.otherwise { - when(nreset) { - assert(counter === values(counter)) - p = printf("values(%d) = %d\n", counter, selected) - } - - } -} - -case class SelectAspect[T <: RawModule, X](selector: T => Seq[X], desired: T => Seq[X]) extends Aspect[T] { - override def toAnnotation(top: T): AnnotationSeq = { - val results = selector(top) - val desiredSeq = desired(top) - assert( - results.length == desiredSeq.length, - s"Failure! Results $results have different length than desired $desiredSeq!" - ) - val mismatches = results.zip(desiredSeq).flatMap { - case (res, des) if res != des => Seq((res, des)) - case other => Nil - } - assert( - mismatches.isEmpty, - s"Failure! The following selected items do not match their desired item:\n" + mismatches.map { - case (res: Select.Serializeable, des: Select.Serializeable) => - s" ${res.serialize} does not match:\n ${des.serialize}" - case (res, des) => s" $res does not match:\n $des" - }.mkString("\n") - ) - Nil - } -} - -class SelectSpec extends ChiselFlatSpec { - - def execute[T <: RawModule, X]( - dut: () => T, - selector: T => Seq[X], - desired: T => Seq[X] - )( - implicit tTag: TypeTag[T] - ): Unit = { - val ret = new chisel3.stage.ChiselStage().run( - Seq( - new chisel3.stage.ChiselGeneratorAnnotation(dut), - SelectAspect(selector, desired), - new chisel3.stage.ChiselOutputFileAnnotation("test_run_dir/Select.fir") - ) - ) - } - - "Test" should "pass if selecting correct registers" in { - execute( - () => new SelectTester(Seq(0, 1, 2)), - { dut: SelectTester => Select.registers(dut) }, - { dut: SelectTester => Seq(dut.counter) } - ) - } - - "Test" should "pass if selecting correct wires" in { - execute( - () => new SelectTester(Seq(0, 1, 2)), - { dut: SelectTester => Select.wires(dut) }, - { dut: SelectTester => Seq(dut.values) } - ) - } - - "Test" should "pass if selecting correct printfs" in { - execute( - () => new SelectTester(Seq(0, 1, 2)), - { dut: SelectTester => Seq(Select.printfs(dut).last.toString) }, - { dut: SelectTester => - Seq( - Select - .Printf( - dut.p, - Seq( - When(Select.ops("eq")(dut).last.asInstanceOf[Bool]), - When(dut.nreset), - WhenNot(dut.overflow) - ), - dut.p.pable, - dut.clock - ) - .toString - ) - } - ) - } - - "Test" should "pass if selecting correct connections" in { - execute( - () => new SelectTester(Seq(0, 1, 2)), - { dut: SelectTester => Select.connectionsTo(dut)(dut.counter) }, - { dut: SelectTester => - Seq( - PredicatedConnect(Nil, dut.counter, dut.added, false), - PredicatedConnect(Seq(When(dut.overflow)), dut.counter, dut.zero, false) - ) - } - ) - } - - "Test" should "pass if selecting ops by kind" in { - execute( - () => new SelectTester(Seq(0, 1, 2)), - { dut: SelectTester => Select.ops("tail")(dut) }, - { dut: SelectTester => Seq(dut.added, dut.zero) } - ) - } - - "Test" should "pass if selecting ops" in { - execute( - () => new SelectTester(Seq(0, 1, 2)), - { dut: SelectTester => Select.ops(dut).collect { case ("tail", d) => d } }, - { dut: SelectTester => Seq(dut.added, dut.zero) } - ) - } - - "Test" should "pass if selecting correct stops" in { - execute( - () => new SelectTester(Seq(0, 1, 2)), - { dut: SelectTester => Seq(Select.stops(dut).last) }, - { dut: SelectTester => - Seq( - Select.Stop( - Seq( - When(Select.ops("eq")(dut)(1).asInstanceOf[Bool]), - When(dut.overflow) - ), - 0, - dut.clock - ) - ) - } - ) - } - - "Blackboxes" should "be supported in Select.instances" in { - class BB extends ExtModule {} - class Top extends RawModule { - val bb = Module(new BB) - } - val top = ChiselGeneratorAnnotation(() => { - new Top() - }).elaborate(1).asInstanceOf[DesignAnnotation[Top]].design - val bbs = Select.collectDeep(top) { case b: BB => b } - assert(bbs.size == 1) - } - - "CloneModuleAsRecord" should "NOT show up in Select aspects" in { - import chisel3.experimental.CloneModuleAsRecord - class Child extends RawModule { - val in = IO(Input(UInt(8.W))) - val out = IO(Output(UInt(8.W))) - out := in - } - class Top extends Module { - val in = IO(Input(UInt(8.W))) - val out = IO(Output(UInt(8.W))) - val inst0 = Module(new Child) - val inst1 = CloneModuleAsRecord(inst0) - inst0.in := in - inst1("in") := inst0.out - out := inst1("out") - } - val top = ChiselGeneratorAnnotation(() => { - new Top() - }).elaborate.collectFirst { case DesignAnnotation(design: Top) => design }.get - Select.collectDeep(top) { case x => x } should equal(Seq(top, top.inst0)) - Select.getDeep(top)(x => Seq(x)) should equal(Seq(top, top.inst0)) - Select.instances(top) should equal(Seq(top.inst0)) - } - - "Using Definition/Instance with Injecting Aspects" should "throw an error" in { - import chisel3.experimental.CloneModuleAsRecord - import chisel3.experimental.hierarchy._ - @instantiable - class Child extends RawModule { - @public val in = IO(Input(UInt(8.W))) - @public val out = IO(Output(UInt(8.W))) - out := in - } - class Top extends Module { - val in = IO(Input(UInt(8.W))) - val out = IO(Output(UInt(8.W))) - val definition = Definition(new Child) - val inst0 = Instance(definition) - val inst1 = Instance(definition) - inst0.in := in - inst1.in := inst0.out - out := inst1.out - } - val top = ChiselGeneratorAnnotation(() => { - new Top() - }).elaborate.collectFirst { case DesignAnnotation(design: Top) => design }.get - intercept[Exception] { Select.collectDeep(top) { case x => x } } - intercept[Exception] { Select.getDeep(top)(x => Seq(x)) } - intercept[Exception] { Select.instances(top) } - } - -} diff --git a/src/test/scala/chiselTests/experimental/DataMirrorSpec.scala b/src/test/scala/chiselTests/experimental/DataMirrorSpec.scala deleted file mode 100644 index 09fdf3c4..00000000 --- a/src/test/scala/chiselTests/experimental/DataMirrorSpec.scala +++ /dev/null @@ -1,91 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.experimental - -import chisel3._ -import chisel3.util.Valid -import chisel3.stage.ChiselStage -import chisel3.experimental.DataMirror -import chiselTests.ChiselFlatSpec - -object DataMirrorSpec { - import org.scalatest.matchers.should.Matchers._ - class GrandChild(parent: RawModule) extends Module { - DataMirror.getParent(this) should be(Some(parent)) - } - class Child(parent: RawModule) extends Module { - val inst = Module(new GrandChild(this)) - DataMirror.getParent(inst) should be(Some(this)) - DataMirror.getParent(this) should be(Some(parent)) - } - class Parent extends Module { - val inst = Module(new Child(this)) - DataMirror.getParent(inst) should be(Some(this)) - DataMirror.getParent(this) should be(None) - } -} - -class DataMirrorSpec extends ChiselFlatSpec { - import DataMirrorSpec._ - - behavior.of("DataMirror") - - def assertBinding(x: Data, io: Boolean, wire: Boolean, reg: Boolean) = { - DataMirror.isIO(x) should be(io) - DataMirror.isWire(x) should be(wire) - DataMirror.isReg(x) should be(reg) - } - - def assertIO(x: Data) = assertBinding(x, true, false, false) - - def assertWire(x: Data) = assertBinding(x, false, true, false) - - def assertReg(x: Data) = assertBinding(x, false, false, true) - - def assertNone(x: Data) = assertBinding(x, false, false, false) - - it should "validate bindings" in { - class MyModule extends Module { - val typ = UInt(4.W) - val vectyp = Vec(8, UInt(4.W)) - val io = IO(new Bundle { - val in = Input(UInt(4.W)) - val vec = Input(vectyp) - val out = Output(UInt(4.W)) - }) - val vec = Wire(vectyp) - val regvec = Reg(vectyp) - val wire = Wire(UInt(4.W)) - val reg = RegNext(wire) - - assertIO(io) - assertIO(io.in) - assertIO(io.out) - assertIO(io.vec(1)) - assertIO(io.vec) - assertWire(vec) - assertWire(vec(0)) - assertWire(wire) - assertReg(reg) - assertReg(regvec) - assertReg(regvec(2)) - assertNone(typ) - assertNone(vectyp) - } - ChiselStage.elaborate(new MyModule) - } - - it should "support getParent for normal modules" in { - ChiselStage.elaborate(new Parent) - } - - it should "support getParent for normal modules even when used in a D/I context" in { - import chisel3.experimental.hierarchy._ - class Top extends Module { - val defn = Definition(new Parent) - val inst = Instance(defn) - DataMirror.getParent(this) should be(None) - } - ChiselStage.elaborate(new Top) - } -} diff --git a/src/test/scala/chiselTests/experimental/DataView.scala b/src/test/scala/chiselTests/experimental/DataView.scala deleted file mode 100644 index cefc893c..00000000 --- a/src/test/scala/chiselTests/experimental/DataView.scala +++ /dev/null @@ -1,557 +0,0 @@ -// See LICENSE for license details. - -package chiselTests.experimental - -import chiselTests.ChiselFlatSpec -import chisel3._ -import chisel3.experimental.dataview._ -import chisel3.experimental.conversions._ -import chisel3.experimental.DataMirror.internal.chiselTypeClone -import chisel3.experimental.{Analog, HWTuple2} -import chisel3.stage.ChiselStage -import chisel3.util.{Decoupled, DecoupledIO} - -object SimpleBundleDataView { - class BundleA(val w: Int) extends Bundle { - val foo = UInt(w.W) - } - class BundleB(val w: Int) extends Bundle { - val bar = UInt(w.W) - } - implicit val v1 = DataView[BundleA, BundleB](a => new BundleB(a.w), _.foo -> _.bar) - implicit val v2 = v1.invert(b => new BundleA(b.w)) -} - -object VecBundleDataView { - class MyBundle extends Bundle { - val foo = UInt(8.W) - val bar = UInt(8.W) - } - implicit val v1: DataView[MyBundle, Vec[UInt]] = DataView(_ => Vec(2, UInt(8.W)), _.foo -> _(1), _.bar -> _(0)) - implicit val v2 = v1.invert(_ => new MyBundle) -} - -object FlatDecoupledDataView { - class FizzBuzz extends Bundle { - val fizz = UInt(8.W) - val buzz = UInt(8.W) - } - class FlatDecoupled extends Bundle { - val valid = Output(Bool()) - val ready = Input(Bool()) - val fizz = Output(UInt(8.W)) - val buzz = Output(UInt(8.W)) - } - implicit val view = DataView[FlatDecoupled, DecoupledIO[FizzBuzz]]( - _ => Decoupled(new FizzBuzz), - _.valid -> _.valid, - _.ready -> _.ready, - _.fizz -> _.bits.fizz, - _.buzz -> _.bits.buzz - ) - implicit val view2 = view.invert(_ => new FlatDecoupled) -} - -class DataViewSpec extends ChiselFlatSpec { - - behavior.of("DataView") - - it should "support simple Bundle viewing" in { - import SimpleBundleDataView._ - class MyModule extends Module { - val in = IO(Input(new BundleA(8))) - val out = IO(Output(new BundleB(8))) - out := in.viewAs[BundleB] - } - val chirrtl = ChiselStage.emitChirrtl(new MyModule) - chirrtl should include("out.bar <= in.foo") - } - - it should "be a bidirectional mapping" in { - import SimpleBundleDataView._ - class MyModule extends Module { - val in = IO(Input(new BundleA(8))) - val out = IO(Output(new BundleB(8))) - out.viewAs[BundleA] := in - } - val chirrtl = ChiselStage.emitChirrtl(new MyModule) - chirrtl should include("out.bar <= in.foo") - } - - it should "handle viewing UInts as UInts" in { - class MyModule extends Module { - val in = IO(Input(UInt(8.W))) - val foo = IO(Output(UInt(8.W))) - val bar = IO(Output(UInt(8.W))) - foo := in.viewAs[UInt] - bar.viewAs[UInt] := in - } - val chirrtl = ChiselStage.emitChirrtl(new MyModule) - chirrtl should include("foo <= in") - chirrtl should include("bar <= in") - } - - it should "handle viewing Analogs as Analogs" in { - class MyModule extends Module { - val foo = IO(Analog(8.W)) - val bar = IO(Analog(8.W)) - foo <> bar.viewAs[Analog] - } - val chirrtl = ChiselStage.emitChirrtl(new MyModule) - chirrtl should include("attach (foo, bar)") - } - - it should "handle viewing Bundles as their same concrete type" in { - class MyBundle extends Bundle { - val foo = UInt(8.W) - } - class MyModule extends Module { - val in = IO(Input(new MyBundle)) - val fizz = IO(Output(new MyBundle)) - val buzz = IO(Output(new MyBundle)) - fizz := in.viewAs[MyBundle] - buzz.viewAs[MyBundle] := in - } - val chirrtl = ChiselStage.emitChirrtl(new MyModule) - chirrtl should include("fizz <= in") - chirrtl should include("buzz <= in") - } - - it should "handle viewing Vecs as their same concrete type" in { - class MyModule extends Module { - val in = IO(Input(Vec(1, UInt(8.W)))) - val fizz = IO(Output(Vec(1, UInt(8.W)))) - val buzz = IO(Output(Vec(1, UInt(8.W)))) - fizz := in.viewAs[Vec[UInt]] - buzz.viewAs[Vec[UInt]] := in - } - val chirrtl = ChiselStage.emitChirrtl(new MyModule) - chirrtl should include("fizz <= in") - chirrtl should include("buzz <= in") - } - - it should "handle viewing Vecs as Bundles and vice versa" in { - import VecBundleDataView._ - class MyModule extends Module { - val in = IO(Input(new MyBundle)) - val out = IO(Output(Vec(2, UInt(8.W)))) - val out2 = IO(Output(Vec(2, UInt(8.W)))) - out := in.viewAs[Vec[UInt]] - out2.viewAs[MyBundle] := in - } - val chirrtl = ChiselStage.emitChirrtl(new MyModule) - chirrtl should include("out[0] <= in.bar") - chirrtl should include("out[1] <= in.foo") - chirrtl should include("out2[0] <= in.bar") - chirrtl should include("out2[1] <= in.foo") - } - - it should "work with bidirectional connections for nested types" in { - import FlatDecoupledDataView._ - class MyModule extends Module { - val enq = IO(Flipped(Decoupled(new FizzBuzz))) - val deq = IO(new FlatDecoupled) - val deq2 = IO(new FlatDecoupled) - deq <> enq.viewAs[FlatDecoupled] - deq2.viewAs[DecoupledIO[FizzBuzz]] <> enq - } - val chirrtl = ChiselStage.emitChirrtl(new MyModule) - chirrtl should include("deq.valid <= enq.valid") - chirrtl should include("enq.ready <= deq.ready") - chirrtl should include("deq.fizz <= enq.bits.fizz") - chirrtl should include("deq.buzz <= enq.bits.buzz") - chirrtl should include("deq2.valid <= enq.valid") - chirrtl should include("enq.ready <= deq2.ready") - chirrtl should include("deq2.fizz <= enq.bits.fizz") - chirrtl should include("deq2.buzz <= enq.bits.buzz") - } - - it should "support viewing a Bundle as a Parent Bundle type" in { - class Foo extends Bundle { - val foo = UInt(8.W) - } - class Bar extends Foo { - val bar = UInt(8.W) - } - class MyModule extends Module { - val fooIn = IO(Input(new Foo)) - val barOut = IO(Output(new Bar)) - barOut.viewAsSupertype(new Foo) := fooIn - - val barIn = IO(Input(new Bar)) - val fooOut = IO(Output(new Foo)) - fooOut := barIn.viewAsSupertype(new Foo) - } - val chirrtl = ChiselStage.emitChirrtl(new MyModule) - chirrtl should include("barOut.foo <= fooIn.foo") - chirrtl should include("fooOut.foo <= barIn.foo") - } - - it should "be easy to make a PartialDataView viewing a Bundle as a Parent Bundle type" in { - class Foo(x: Int) extends Bundle { - val foo = UInt(x.W) - } - class Bar(val x: Int) extends Foo(x) { - val bar = UInt(x.W) - } - implicit val view = PartialDataView.supertype[Bar, Foo](b => new Foo(b.x)) - class MyModule extends Module { - val fooIn = IO(Input(new Foo(8))) - val barOut = IO(Output(new Bar(8))) - barOut.viewAs[Foo] := fooIn - - val barIn = IO(Input(new Bar(8))) - val fooOut = IO(Output(new Foo(8))) - fooOut := barIn.viewAs[Foo] - } - val chirrtl = ChiselStage.emitChirrtl(new MyModule) - chirrtl should include("barOut.foo <= fooIn.foo") - chirrtl should include("fooOut.foo <= barIn.foo") - } - - it should "error if viewing a parent Bundle as a child Bundle type" in { - assertTypeError(""" - class Foo extends Bundle { - val foo = UInt(8.W) - } - class Bar extends Foo { - val bar = UInt(8.W) - } - class MyModule extends Module { - val barIn = IO(Input(new Bar)) - val fooOut = IO(Output(new Foo)) - fooOut.viewAs(new Bar) := barIn - } - """) - } - - it should "work in UInt operations" in { - class MyBundle extends Bundle { - val value = UInt(8.W) - } - class MyModule extends Module { - val a = IO(Input(UInt(8.W))) - val b = IO(Input(new MyBundle)) - val cond = IO(Input(Bool())) - val and, mux, bitsCat = IO(Output(UInt(8.W))) - // Chisel unconditionally emits a node, so name it at least - val x = a.viewAs[UInt] & b.viewAs[MyBundle].value - and.viewAs[UInt] := x - - val y = Mux(cond.viewAs[Bool], a.viewAs[UInt], b.value.viewAs[UInt]) - mux.viewAs[UInt] := y - - // TODO should we have a macro so that we don't need .apply? - val aBits = a.viewAs[UInt].apply(3, 0) - val bBits = b.viewAs[MyBundle].value(3, 0) - val abCat = aBits.viewAs[UInt] ## bBits.viewAs[UInt] - bitsCat := abCat - } - val chirrtl = ChiselStage.emitChirrtl(new MyModule) - val expected = List( - "node x = and(a, b.value)", - "and <= x", - "node y = mux(cond, a, b.value)", - "mux <= y", - "node aBits = bits(a, 3, 0)", - "node bBits = bits(b.value, 3, 0)", - "node abCat = cat(aBits, bBits)", - "bitsCat <= abCat" - ) - for (line <- expected) { - chirrtl should include(line) - } - } - - it should "support .asUInt of Views" in { - import VecBundleDataView._ - class MyModule extends Module { - val barIn = IO(Input(new MyBundle)) - val fooOut = IO(Output(UInt())) - val cat = barIn.viewAs[Vec[UInt]].asUInt - fooOut := cat - } - val chirrtl = ChiselStage.emitChirrtl(new MyModule) - chirrtl should include("node cat = cat(barIn.foo, barIn.bar)") - chirrtl should include("fooOut <= cat") - } - - it should "be composable" in { - // Given DataView[A, B] and DataView[B, C], derive DataView[A, C] - class Foo(val foo: UInt) extends Bundle - class Bar(val bar: UInt) extends Bundle - class Fizz(val fizz: UInt) extends Bundle - - implicit val foo2bar = DataView[Foo, Bar](f => new Bar(chiselTypeClone(f.foo)), _.foo -> _.bar) - implicit val bar2fizz = DataView[Bar, Fizz](b => new Fizz(chiselTypeClone(b.bar)), _.bar -> _.fizz) - - implicit val foo2fizz: DataView[Foo, Fizz] = foo2bar.andThen(bar2fizz) - - class MyModule extends Module { - val a, b = IO(Input(new Foo(UInt(8.W)))) - val y, z = IO(Output(new Fizz(UInt(8.W)))) - y := a.viewAs[Fizz] - z := b.viewAs[Bar].viewAs[Fizz] - } - val chirrtl = ChiselStage.emitChirrtl(new MyModule) - chirrtl should include("y.fizz <= a.foo") - chirrtl should include("z.fizz <= b.foo") - } - - it should "enable using Seq like Data" in { - class MyModule extends Module { - val a, b, c, d = IO(Input(UInt(8.W))) - val sel = IO(Input(Bool())) - val y, z = IO(Output(UInt(8.W))) - // Unclear why the implicit conversion does not work in this case for Seq - // That being said, it's easy enough to cast via `.viewAs` with or without - Seq(y, z) := Mux(sel, Seq(a, b).viewAs, Seq(c, d).viewAs[Vec[UInt]]) - } - // Verilog instead of CHIRRTL because the optimizations make it much prettier - val verilog = ChiselStage.emitVerilog(new MyModule) - verilog should include("assign y = sel ? a : c;") - verilog should include("assign z = sel ? b : d;") - } - - // This example should be turned into a built-in feature - it should "enable viewing Seqs as Vecs" in { - - class MyModule extends Module { - val a, b, c = IO(Input(UInt(8.W))) - val x, y, z = IO(Output(UInt(8.W))) - Seq(x, y, z) := VecInit(a, b, c) - } - // Verilog instead of CHIRRTL because the optimizations make it much prettier - val verilog = ChiselStage.emitVerilog(new MyModule) - verilog should include("assign x = a;") - verilog should include("assign y = b;") - verilog should include("assign z = c;") - } - - it should "support recursive composition of views" in { - class MyModule extends Module { - val a, b, c, d = IO(Input(UInt(8.W))) - val w, x, y, z = IO(Output(UInt(8.W))) - - // A little annoying that we need the type annotation on VecInit to get the implicit conversion to work - // Note that one can just use the Seq on the RHS so there is an alternative (may lack discoverability) - // We could also overload `VecInit` instead of relying on the implicit conversion - Seq((w, x), (y, z)) := VecInit[HWTuple2[UInt, UInt]]((a, b), (c, d)) - } - val verilog = ChiselStage.emitVerilog(new MyModule) - verilog should include("assign w = a;") - verilog should include("assign x = b;") - verilog should include("assign y = c;") - verilog should include("assign z = d;") - } - - it should "support dynamic indexing for Vec identity views" in { - class MyModule extends Module { - val dataIn = IO(Input(UInt(8.W))) - val addr = IO(Input(UInt(2.W))) - val dataOut = IO(Output(UInt(8.W))) - - val vec = RegInit(0.U.asTypeOf(Vec(4, UInt(8.W)))) - val view = vec.viewAs[Vec[UInt]] - // Dynamic indexing is more of a "generator" in Chisel3 than an individual node - // This style is not recommended, this is just testing the behavior - val selected = view(addr) - selected := dataIn - dataOut := selected - } - val chirrtl = ChiselStage.emitChirrtl(new MyModule) - chirrtl should include("vec[addr] <= dataIn") - chirrtl should include("dataOut <= vec[addr]") - } - - it should "support dynamic indexing for Vecs that correspond 1:1 in a view" in { - class MyBundle extends Bundle { - val foo = Vec(4, UInt(8.W)) - val bar = UInt(2.W) - } - implicit val myView = DataView[(Vec[UInt], UInt), MyBundle]( - _ => new MyBundle, - _._1 -> _.foo, - _._2 -> _.bar - ) - class MyModule extends Module { - val dataIn = IO(Input(UInt(8.W))) - val addr = IO(Input(UInt(2.W))) - val dataOut = IO(Output(UInt(8.W))) - - val vec = RegInit(0.U.asTypeOf(Vec(4, UInt(8.W)))) - val addrReg = Reg(UInt(2.W)) - val view = (vec, addrReg).viewAs[MyBundle] - // Dynamic indexing is more of a "generator" in Chisel3 than an individual node - // This style is not recommended, this is just testing the behavior - val selected = view.foo(view.bar) - view.bar := addr - selected := dataIn - dataOut := selected - } - val chirrtl = ChiselStage.emitChirrtl(new MyModule) - chirrtl should include("vec[addrReg] <= dataIn") - chirrtl should include("dataOut <= vec[addrReg]") - } - - it should "error if you try to dynamically index a Vec view that does not correspond to a Vec target" in { - class MyModule extends Module { - val inA, inB = IO(Input(UInt(8.W))) - val outA, outB = IO(Output(UInt(8.W))) - val idx = IO(Input(UInt(1.W))) - - val a, b, c, d = RegInit(0.U) - - // Dynamic indexing is more of a "generator" in Chisel3 than an individual node - // This style is not recommended, this is just testing the behavior - val selected = Seq((a, b), (c, d)).apply(idx) - selected := (inA, inB) - (outA, outB) := selected - } - (the[InvalidViewException] thrownBy { - ChiselStage.emitChirrtl(new MyModule) - }).getMessage should include("Dynamic indexing of Views is not yet supported") - } - - it should "error if the mapping is non-total in the view" in { - class MyBundle(val foo: UInt, val bar: UInt) extends Bundle - implicit val dv = DataView[UInt, MyBundle](_ => new MyBundle(UInt(), UInt()), _ -> _.bar) - class MyModule extends Module { - val tpe = new MyBundle(UInt(8.W), UInt(8.W)) - val in = IO(Input(UInt(8.W))) - val out = IO(Output(tpe)) - out := in.viewAs[MyBundle] - } - val err = the[InvalidViewException] thrownBy (ChiselStage.emitVerilog(new MyModule)) - err.toString should include("View field '_.foo' is missing") - } - - it should "error if the mapping is non-total in the target" in { - implicit val dv = DataView[(UInt, UInt), UInt](_ => UInt(), _._1 -> _) - class MyModule extends Module { - val a, b = IO(Input(UInt(8.W))) - val out = IO(Output(UInt(8.W))) - out := (a, b).viewAs[UInt] - } - val err = the[InvalidViewException] thrownBy (ChiselStage.emitVerilog(new MyModule)) - err.toString should include("Target field '_._2' is missing") - } - - it should "error if the mapping contains Data that are not part of the Target" in { - class BundleA extends Bundle { - val foo = UInt(8.W) - } - class BundleB extends Bundle { - val fizz = UInt(8.W) - val buzz = UInt(8.W) - } - implicit val dv = DataView[BundleA, BundleB](_ => new BundleB, _.foo -> _.fizz, (_, b) => (3.U, b.buzz)) - class MyModule extends Module { - val in = IO(Input(new BundleA)) - val out = IO(Output(new BundleB)) - out := in.viewAs[BundleB] - } - val err = the[InvalidViewException] thrownBy (ChiselStage.emitVerilog(new MyModule)) - err.toString should include("View mapping must only contain Elements within the Target") - } - - it should "error if the mapping contains Data that are not part of the View" in { - class BundleA extends Bundle { - val foo = UInt(8.W) - } - class BundleB extends Bundle { - val fizz = UInt(8.W) - val buzz = UInt(8.W) - } - implicit val dv = DataView[BundleA, BundleB](_ => new BundleB, _.foo -> _.fizz, (_, b) => (3.U, b.buzz)) - implicit val dv2 = dv.invert(_ => new BundleA) - class MyModule extends Module { - val in = IO(Input(new BundleA)) - val out = IO(Output(new BundleB)) - out.viewAs[BundleA] := in - } - val err = the[InvalidViewException] thrownBy (ChiselStage.emitVerilog(new MyModule)) - err.toString should include("View mapping must only contain Elements within the View") - } - - it should "error if a view has a width that does not match the target" in { - class BundleA extends Bundle { - val foo = UInt(8.W) - } - class BundleB extends Bundle { - val bar = UInt(4.W) - } - implicit val dv = DataView[BundleA, BundleB](_ => new BundleB, _.foo -> _.bar) - class MyModule extends Module { - val in = IO(Input(new BundleA)) - val out = IO(Output(new BundleB)) - out := in.viewAs[BundleB] - } - val err = the[InvalidViewException] thrownBy ChiselStage.emitChirrtl(new MyModule) - val expected = """View field _\.bar UInt<4> has width <4> that is incompatible with target value .+'s width <8>""".r - (err.getMessage should fullyMatch).regex(expected) - } - - it should "error if a view has a known width when the target width is unknown" in { - class BundleA extends Bundle { - val foo = UInt() - } - class BundleB extends Bundle { - val bar = UInt(4.W) - } - implicit val dv = DataView[BundleA, BundleB](_ => new BundleB, _.foo -> _.bar) - class MyModule extends Module { - val in = IO(Input(new BundleA)) - val out = IO(Output(new BundleB)) - out := in.viewAs[BundleB] - } - val err = the[InvalidViewException] thrownBy ChiselStage.emitChirrtl(new MyModule) - val expected = - """View field _\.bar UInt<4> has width <4> that is incompatible with target value .+'s width <unknown>""".r - (err.getMessage should fullyMatch).regex(expected) - } - - it should "support invalidation" in { - class MyModule extends Module { - val a, b, c, d, e, f = IO(Output(UInt(8.W))) - val foo = (a, b).viewAs - val bar = (c, d).viewAs - val fizz = (e, f).viewAs - foo := DontCare - bar <> DontCare - fizz._1 := DontCare - fizz._2 <> DontCare - } - - val chirrtl = ChiselStage.emitChirrtl(new MyModule) - val expected = ('a' to 'f').map(c => s"$c is invalid") - for (line <- expected) { - chirrtl should include(line) - } - } - - behavior.of("PartialDataView") - - it should "still error if the mapping is non-total in the view" in { - class MyBundle(val foo: UInt, val bar: UInt) extends Bundle - implicit val dv = PartialDataView[UInt, MyBundle](_ => new MyBundle(UInt(), UInt()), _ -> _.bar) - class MyModule extends Module { - val in = IO(Input(UInt(8.W))) - val out = IO(Output(new MyBundle(UInt(8.W), UInt(8.W)))) - out := in.viewAs[MyBundle] - } - val err = the[InvalidViewException] thrownBy (ChiselStage.emitVerilog(new MyModule)) - err.toString should include("View field '_.foo' is missing") - } - - it should "NOT error if the mapping is non-total in the target" in { - implicit val dv = PartialDataView[(UInt, UInt), UInt](_ => UInt(), _._2 -> _) - class MyModule extends Module { - val a, b = IO(Input(UInt(8.W))) - val out = IO(Output(UInt(8.W))) - out := (a, b).viewAs[UInt] - } - val verilog = ChiselStage.emitVerilog(new MyModule) - verilog should include("assign out = b;") - } -} diff --git a/src/test/scala/chiselTests/experimental/DataViewIntegrationSpec.scala b/src/test/scala/chiselTests/experimental/DataViewIntegrationSpec.scala deleted file mode 100644 index 4704a942..00000000 --- a/src/test/scala/chiselTests/experimental/DataViewIntegrationSpec.scala +++ /dev/null @@ -1,57 +0,0 @@ -// See LICENSE for license details. - -package chiselTests.experimental - -import chisel3._ -import chisel3.experimental.{BaseModule, ExtModule} -import chisel3.experimental.dataview._ -import chisel3.util.{log2Ceil, Decoupled, DecoupledIO, Queue, QueueIO} -import chiselTests.ChiselFlatSpec -import firrtl.transforms.DontTouchAnnotation - -// Let's put it all together! -object DataViewIntegrationSpec { - - class QueueIntf[T <: Data](gen: T, entries: Int) extends Bundle { - val ports = new QueueIO(gen, entries) - // Let's grab a reference to something internal too - // Output because can't have directioned and undirectioned stuff - val enq_ptr = Output(UInt(log2Ceil(entries).W)) - } - - // It's not clear if a view of a Module ever _can_ be total since internal nodes are part of the Module - implicit def queueView[T <: Data] = PartialDataView[Queue[T], QueueIntf[T]]( - q => new QueueIntf(q.gen, q.entries), - _.io -> _.ports, - // Some token internal signal - _.enq_ptr.value -> _.enq_ptr - ) - - object MyQueue { - def apply[T <: Data](enq: DecoupledIO[T], n: Int): QueueIntf[T] = { - val queue = Module(new Queue[T](enq.bits.cloneType, n)) - val view = queue.viewAs[QueueIntf[T]] - view.ports.enq <> enq - view - } - } - - class MyModule extends Module { - val enq = IO(Flipped(Decoupled(UInt(8.W)))) - val deq = IO(Decoupled(UInt(8.W))) - - val queue = MyQueue(enq, 4) - deq <> queue.ports.deq - dontTouch(queue.enq_ptr) - } -} - -class DataViewIntegrationSpec extends ChiselFlatSpec { - import DataViewIntegrationSpec.MyModule - - "Users" should "be able to view and annotate Modules" in { - val (_, annos) = getFirrtlAndAnnos(new MyModule) - val ts = annos.collect { case DontTouchAnnotation(t) => t.serialize } - ts should equal(Seq("~MyModule|Queue>enq_ptr_value")) - } -} diff --git a/src/test/scala/chiselTests/experimental/DataViewTargetSpec.scala b/src/test/scala/chiselTests/experimental/DataViewTargetSpec.scala deleted file mode 100644 index ddeeab6e..00000000 --- a/src/test/scala/chiselTests/experimental/DataViewTargetSpec.scala +++ /dev/null @@ -1,176 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.experimental - -import chisel3._ -import chisel3.experimental.dataview._ -import chisel3.experimental.conversions._ -import chisel3.experimental.{annotate, ChiselAnnotation} -import chiselTests.ChiselFlatSpec - -object DataViewTargetSpec { - import firrtl.annotations._ - private case class DummyAnno(target: ReferenceTarget, id: Int) extends SingleTargetAnnotation[ReferenceTarget] { - override def duplicate(n: ReferenceTarget) = this.copy(target = n) - } - private def mark(d: Data, id: Int) = annotate(new ChiselAnnotation { - override def toFirrtl: Annotation = DummyAnno(d.toTarget, id) - }) - private def markAbs(d: Data, id: Int) = annotate(new ChiselAnnotation { - override def toFirrtl: Annotation = DummyAnno(d.toAbsoluteTarget, id) - }) -} - -class DataViewTargetSpec extends ChiselFlatSpec { - import DataViewTargetSpec._ - private val checks: Seq[Data => String] = Seq( - _.toTarget.toString, - _.toAbsoluteTarget.toString, - _.instanceName, - _.pathName, - _.parentPathName, - _.parentModName - ) - - // Check helpers - private def checkAll(impl: Data, refs: String*): Unit = { - refs.size should be(checks.size) - for ((check, value) <- checks.zip(refs)) { - check(impl) should be(value) - } - } - private def checkSameAs(impl: Data, refs: Data*): Unit = - for (ref <- refs) { - checkAll(impl, checks.map(_(ref)): _*) - } - - behavior.of("DataView Naming") - - it should "support views of Elements" in { - class MyChild extends Module { - val out = IO(Output(UInt(8.W))) - val insideView = out.viewAs[UInt] - out := 0.U - } - class MyParent extends Module { - val out = IO(Output(UInt(8.W))) - val inst = Module(new MyChild) - out := inst.out - } - val m = elaborateAndGetModule(new MyParent) - val outsideView = m.inst.out.viewAs[UInt] - checkSameAs(m.inst.out, m.inst.insideView, outsideView) - } - - it should "support 1:1 mappings of Aggregates and their children" in { - class MyBundle extends Bundle { - val foo = UInt(8.W) - val bars = Vec(2, UInt(8.W)) - } - implicit val dv = - DataView[MyBundle, Vec[UInt]](_ => Vec(3, UInt(8.W)), _.foo -> _(0), _.bars(0) -> _(1), _.bars(1) -> _(2)) - class MyChild extends Module { - val out = IO(Output(new MyBundle)) - val outView = out.viewAs[Vec[UInt]] // Note different type - val outFooView = out.foo.viewAs[UInt] - val outBarsView = out.bars.viewAs[Vec[UInt]] - val outBars0View = out.bars(0).viewAs[UInt] - out := 0.U.asTypeOf(new MyBundle) - } - class MyParent extends Module { - val out = IO(Output(new MyBundle)) - val inst = Module(new MyChild) - out := inst.out - } - val m = elaborateAndGetModule(new MyParent) - val outView = m.inst.out.viewAs[Vec[UInt]] // Note different type - val outFooView = m.inst.out.foo.viewAs[UInt] - val outBarsView = m.inst.out.bars.viewAs[Vec[UInt]] - val outBars0View = m.inst.out.bars(0).viewAs[UInt] - - checkSameAs(m.inst.out, m.inst.outView, outView) - checkSameAs(m.inst.out.foo, m.inst.outFooView, m.inst.outView(0), outFooView, outView(0)) - checkSameAs(m.inst.out.bars, m.inst.outBarsView, outBarsView) - checkSameAs( - m.inst.out.bars(0), - m.inst.outBars0View, - outBars0View, - m.inst.outView(1), - outView(1), - m.inst.outBarsView(0), - outBarsView(0) - ) - } - - // Ideally this would work 1:1 but that requires changing the binding - it should "support annotation renaming of Aggregate children of Aggregate views" in { - class MyBundle extends Bundle { - val foo = Vec(2, UInt(8.W)) - } - class MyChild extends Module { - val out = IO(Output(new MyBundle)) - val outView = out.viewAs[MyBundle] - mark(out.foo, 0) - mark(outView.foo, 1) - markAbs(out.foo, 2) - markAbs(outView, 3) - out := 0.U.asTypeOf(new MyBundle) - } - class MyParent extends Module { - val out = IO(Output(new MyBundle)) - val inst = Module(new MyChild) - out := inst.out - } - val (_, annos) = getFirrtlAndAnnos(new MyParent) - val pairs = annos.collect { case DummyAnno(t, idx) => (idx, t.toString) }.sortBy(_._1) - val expected = Seq( - 0 -> "~MyParent|MyChild>out.foo", - 1 -> "~MyParent|MyChild>out.foo", - 2 -> "~MyParent|MyParent/inst:MyChild>out.foo", - 3 -> "~MyParent|MyParent/inst:MyChild>out" - ) - pairs should equal(expected) - } - - it should "support annotating views that cannot be mapped to a single ReferenceTarget" in { - class MyBundle extends Bundle { - val a, b = Input(UInt(8.W)) - val c, d = Output(UInt(8.W)) - } - // Note that each use of a Tuple as Data causes an implicit conversion creating a View - class MyChild extends Module { - val io = IO(new MyBundle) - (io.c, io.d) := (io.a, io.b) - // The type annotations create the views via the implicit conversion - val view1: Data = (io.a, io.b) - val view2: Data = (io.c, io.d) - mark(view1, 0) - mark(view2, 1) - markAbs(view1, 2) - markAbs(view2, 3) - mark((io.b, io.d), 4) // Mix it up for fun - } - class MyParent extends Module { - val io = IO(new MyBundle) - val inst = Module(new MyChild) - io <> inst.io - } - val (_, annos) = getFirrtlAndAnnos(new MyParent) - val pairs = annos.collect { case DummyAnno(t, idx) => (idx, t.toString) }.sorted - val expected = Seq( - 0 -> "~MyParent|MyChild>io.a", - 0 -> "~MyParent|MyChild>io.b", - 1 -> "~MyParent|MyChild>io.c", - 1 -> "~MyParent|MyChild>io.d", - 2 -> "~MyParent|MyParent/inst:MyChild>io.a", - 2 -> "~MyParent|MyParent/inst:MyChild>io.b", - 3 -> "~MyParent|MyParent/inst:MyChild>io.c", - 3 -> "~MyParent|MyParent/inst:MyChild>io.d", - 4 -> "~MyParent|MyChild>io.b", - 4 -> "~MyParent|MyChild>io.d" - ) - pairs should equal(expected) - } - - // TODO check these properties when using @instance API (especially preservation of totality) -} diff --git a/src/test/scala/chiselTests/experimental/FlatIOSpec.scala b/src/test/scala/chiselTests/experimental/FlatIOSpec.scala deleted file mode 100644 index fb3f64c7..00000000 --- a/src/test/scala/chiselTests/experimental/FlatIOSpec.scala +++ /dev/null @@ -1,68 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.experimental - -import chisel3._ -import chisel3.util.Valid -import chisel3.stage.ChiselStage.emitChirrtl -import chisel3.experimental.{Analog, FlatIO} -import chiselTests.ChiselFlatSpec - -class FlatIOSpec extends ChiselFlatSpec { - behavior.of("FlatIO") - - it should "create ports without a prefix" in { - class MyModule extends RawModule { - val io = FlatIO(new Bundle { - val in = Input(UInt(8.W)) - val out = Output(UInt(8.W)) - }) - io.out := io.in - } - val chirrtl = emitChirrtl(new MyModule) - chirrtl should include("input in : UInt<8>") - chirrtl should include("output out : UInt<8>") - chirrtl should include("out <= in") - } - - it should "support bulk connections between FlatIOs and regular IOs" in { - class MyModule extends RawModule { - val in = FlatIO(Input(Valid(UInt(8.W)))) - val out = IO(Output(Valid(UInt(8.W)))) - out := in - } - val chirrtl = emitChirrtl(new MyModule) - chirrtl should include("out.bits <= bits") - chirrtl should include("out.valid <= valid") - } - - it should "dynamically indexing Vecs inside of FlatIOs" in { - class MyModule extends RawModule { - val io = FlatIO(new Bundle { - val addr = Input(UInt(2.W)) - val in = Input(Vec(4, UInt(8.W))) - val out = Output(Vec(4, UInt(8.W))) - }) - io.out(io.addr) := io.in(io.addr) - } - val chirrtl = emitChirrtl(new MyModule) - chirrtl should include("out[addr] <= in[addr]") - } - - it should "support Analog members" in { - class MyBundle extends Bundle { - val foo = Output(UInt(8.W)) - val bar = Analog(8.W) - } - class MyModule extends RawModule { - val io = FlatIO(new Bundle { - val in = Flipped(new MyBundle) - val out = new MyBundle - }) - io.out <> io.in - } - val chirrtl = emitChirrtl(new MyModule) - chirrtl should include("out.foo <= in.foo") - chirrtl should include("attach (out.bar, in.bar)") - } -} diff --git a/src/test/scala/chiselTests/experimental/ForceNames.scala b/src/test/scala/chiselTests/experimental/ForceNames.scala deleted file mode 100644 index 9ba825c4..00000000 --- a/src/test/scala/chiselTests/experimental/ForceNames.scala +++ /dev/null @@ -1,128 +0,0 @@ -// See LICENSE for license details. - -package chiselTests - -import firrtl._ -import chisel3._ -import chisel3.experimental.annotate -import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} -import chisel3.util.experimental.{forceName, ForceNameAnnotation, ForceNamesTransform, InlineInstance} -import firrtl.annotations.{Annotation, ReferenceTarget} -import firrtl.options.{Dependency, TargetDirAnnotation} -import firrtl.stage.RunFirrtlTransformAnnotation -import logger.{LogLevel, LogLevelAnnotation} - -/** Object containing Modules used for testing */ -object ForceNamesHierarchy { - 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 - forceName(out, "outt") - } - 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) - forceName(inst, "inst") - inst.in := in - out := inst.out - } - class MyLeaf extends Module { - val in = IO(Input(UInt(3.W))) - val out = IO(Output(UInt(3.W))) - out := in - } - class RenamePortsExample extends Module { - val in = IO(Input(UInt(3.W))) - val out = IO(Output(UInt(3.W))) - val inst = Module(new MyLeaf) - inst.in := in - out := inst.out - forceName(inst.in, "inn") - } - 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 Module { - val in = IO(new Bundle { - val a = Input(UInt(3.W)) - val b = Input(UInt(3.W)) - }) - val out = IO(Output(UInt(3.W))) - out := in.a + in.b - } -} - -class ForceNamesSpec extends ChiselFlatSpec with Utils { - - def run[T <: RawModule]( - dut: => T, - testName: String, - inputAnnos: Seq[Annotation] = Nil, - info: LogLevel.Value = LogLevel.None - ): Iterable[String] = { - def stage = new ChiselStage { - override val targets = Seq( - Dependency[chisel3.stage.phases.Elaborate], - Dependency[chisel3.stage.phases.Convert], - Dependency[firrtl.stage.phases.Compiler] - ) - } - - val annos = List( - TargetDirAnnotation("test_run_dir/ForceNames"), - LogLevelAnnotation(info), - ChiselGeneratorAnnotation(() => dut) - ) ++ inputAnnos - - val ret = stage.execute(Array(), annos) - val verilog = ret.collectFirst { - case e: EmittedVerilogCircuitAnnotation => e.value.value - }.get - - verilog.split("\\\n") - } - "Force Names on a wrapping instance" should "work" in { - val verilog = run(new ForceNamesHierarchy.WrapperExample, "wrapper") - exactly(1, verilog) should include("MyLeaf inst") - } - "Force Names on an instance port" should "work" in { - val verilog = run(new ForceNamesHierarchy.RenamePortsExample, "instports") - atLeast(1, verilog) should include("input [2:0] inn") - } - "Force Names with a conflicting name" should "error" in { - intercept[CustomTransformException] { - run(new ForceNamesHierarchy.ConflictingName, "conflicts") - } - } - "Force Names of an intermediate bundle" should "error" in { - intercept[CustomTransformException] { - run( - new ForceNamesHierarchy.BundleName, - "bundlename", - Seq(ForceNameAnnotation(ReferenceTarget("BundleName", "BundleName", Nil, "in", Nil), "inn")) - ) - } - } - - "Force Name of non-hardware value" should "warn" in { - class Example extends Module { - val tpe = UInt(8.W) - forceName(tpe, "foobar") - - val in = IO(Input(tpe)) - val out = IO(Output(tpe)) - out := in - } - - val (log, foo) = grabLog(chisel3.stage.ChiselStage.elaborate(new Example)) - log should include("deprecated") - log should include("Using forceName 'foobar' on non-hardware value UInt<8>") - } -} diff --git a/src/test/scala/chiselTests/experimental/GroupSpec.scala b/src/test/scala/chiselTests/experimental/GroupSpec.scala deleted file mode 100644 index 5e0c34bb..00000000 --- a/src/test/scala/chiselTests/experimental/GroupSpec.scala +++ /dev/null @@ -1,115 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.experimental - -import chiselTests.ChiselFlatSpec -import chisel3._ -import chisel3.RawModule -import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} -import chisel3.util.experimental.group -import firrtl.analyses.InstanceGraph -import firrtl.options.TargetDirAnnotation -import firrtl.stage.CompilerAnnotation -import firrtl.{LowFirrtlCompiler, ir => fir} - -import scala.collection.mutable - -class GroupSpec extends ChiselFlatSpec { - - def collectInstances(c: fir.Circuit, top: Option[String] = None): Seq[String] = - new InstanceGraph(c).fullHierarchy.values.flatten.toSeq - .map(v => (top.getOrElse(v.head.name) +: v.tail.map(_.name)).mkString(".")) - - def collectDeclarations(m: fir.DefModule): Set[String] = { - val decs = mutable.HashSet[String]() - def onStmt(s: fir.Statement): fir.Statement = s.mapStmt(onStmt) match { - case d: fir.IsDeclaration => decs += d.name; d - case other => other - } - m.mapStmt(onStmt) - decs.toSet - } - - def lower[T <: RawModule](gen: () => T): fir.Circuit = { - (new ChiselStage) - .execute(Array("--compiler", "low", "--target-dir", "test_run_dir"), Seq(ChiselGeneratorAnnotation(gen))) - .collectFirst { - case firrtl.stage.FirrtlCircuitAnnotation(circuit) => circuit - } - .get - } - - "Module Grouping" should "compile to low FIRRTL" in { - class MyModule extends Module { - val io = IO(new Bundle { - val a = Input(Bool()) - val b = Output(Bool()) - }) - val reg1 = RegInit(0.U) - reg1 := io.a - val reg2 = RegNext(reg1) - io.b := reg2 - group(Seq(reg1, reg2), "DosRegisters", "doubleReg") - } - - val firrtlCircuit = lower(() => new MyModule) - firrtlCircuit.modules.collect { - case m: fir.Module if m.name == "MyModule" => - Set("doubleReg") should be(collectDeclarations(m)) - case m: fir.Module if m.name == "DosRegisters" => - Set("reg1", "reg2") should be(collectDeclarations(m)) - } - val instances = collectInstances(firrtlCircuit, Some("MyModule")).toSet - Set("MyModule", "MyModule.doubleReg") should be(instances) - } - - "Module Grouping" should "not include intermediate registers" in { - class MyModule extends Module { - val io = IO(new Bundle { - val a = Input(Bool()) - val b = Output(Bool()) - }) - val reg1 = RegInit(0.U) - reg1 := io.a - val reg2 = RegNext(reg1) - val reg3 = RegNext(reg2) - io.b := reg3 - group(Seq(reg1, reg3), "DosRegisters", "doubleReg") - } - - val firrtlCircuit = lower(() => new MyModule) - firrtlCircuit.modules.collect { - case m: fir.Module if m.name == "MyModule" => - Set("reg2", "doubleReg") should be(collectDeclarations(m)) - case m: fir.Module if m.name == "DosRegisters" => - Set("reg1", "reg3") should be(collectDeclarations(m)) - } - val instances = collectInstances(firrtlCircuit, Some("MyModule")).toSet - Set("MyModule", "MyModule.doubleReg") should be(instances) - } - - "Module Grouping" should "include intermediate wires" in { - class MyModule extends Module { - val io = IO(new Bundle { - val a = Input(Bool()) - val b = Output(Bool()) - }) - val reg1 = RegInit(0.U) - reg1 := io.a - val wire = WireInit(reg1) - val reg3 = RegNext(wire) - io.b := reg3 - group(Seq(reg1, reg3), "DosRegisters", "doubleReg") - } - - val firrtlCircuit = lower(() => new MyModule) - firrtlCircuit.modules.collect { - case m: fir.Module if m.name == "MyModule" => - Set("doubleReg") should be(collectDeclarations(m)) - case m: fir.Module if m.name == "DosRegisters" => - Set("reg1", "reg3", "wire") should be(collectDeclarations(m)) - } - val instances = collectInstances(firrtlCircuit, Some("MyModule")).toSet - Set("MyModule", "MyModule.doubleReg") should be(instances) - } -} diff --git a/src/test/scala/chiselTests/experimental/ModuleDataProductSpec.scala b/src/test/scala/chiselTests/experimental/ModuleDataProductSpec.scala deleted file mode 100644 index 713f9d04..00000000 --- a/src/test/scala/chiselTests/experimental/ModuleDataProductSpec.scala +++ /dev/null @@ -1,91 +0,0 @@ -// See LICENSE for license details. - -package chiselTests.experimental - -import chisel3._ -import chisel3.experimental.{BaseModule, ExtModule} -import chisel3.experimental.dataview.DataProduct -import chiselTests.ChiselFlatSpec - -object ModuleDataProductSpec { - class MyBundle extends Bundle { - val foo = UInt(8.W) - val bar = UInt(8.W) - } - trait MyIntf extends BaseModule { - val in = IO(Input(new MyBundle)) - val out = IO(Output(new MyBundle)) - } - class Passthrough extends RawModule { - val in = IO(Input(UInt(8.W))) - val out = IO(Output(UInt(8.W))) - out := in - } - class MyUserModule extends Module with MyIntf { - val inst = Module(new Passthrough) - inst.in := in.foo - val r = RegNext(in) - out := r - } - - class MyExtModule extends ExtModule with MyIntf - class MyExtModuleWrapper extends RawModule with MyIntf { - val inst = Module(new MyExtModule) - inst.in := in - out := inst.out - } -} - -class ModuleDataProductSpec extends ChiselFlatSpec { - import ModuleDataProductSpec._ - - behavior.of("DataProduct") - - it should "work for UserModules (recursively)" in { - val m = elaborateAndGetModule(new MyUserModule) - val expected = Seq( - m.clock -> "m.clock", - m.reset -> "m.reset", - m.in -> "m.in", - m.in.foo -> "m.in.foo", - m.in.bar -> "m.in.bar", - m.out -> "m.out", - m.out.foo -> "m.out.foo", - m.out.bar -> "m.out.bar", - m.r -> "m.r", - m.r.foo -> "m.r.foo", - m.r.bar -> "m.r.bar", - m.inst.in -> "m.inst.in", - m.inst.out -> "m.inst.out" - ) - - val impl = implicitly[DataProduct[MyUserModule]] - val set = impl.dataSet(m) - for ((d, _) <- expected) { - set(d) should be(true) - } - val it = impl.dataIterator(m, "m") - it.toList should contain theSameElementsAs (expected) - } - - it should "work for (wrapped) ExtModules" in { - val m = elaborateAndGetModule(new MyExtModuleWrapper).inst - val expected = Seq( - m.in -> "m.in", - m.in.foo -> "m.in.foo", - m.in.bar -> "m.in.bar", - m.out -> "m.out", - m.out.foo -> "m.out.foo", - m.out.bar -> "m.out.bar" - ) - - val impl = implicitly[DataProduct[MyExtModule]] - val set = impl.dataSet(m) - for ((d, _) <- expected) { - set(d) should be(true) - } - val it = impl.dataIterator(m, "m") - it.toList should contain theSameElementsAs (expected) - } - -} diff --git a/src/test/scala/chiselTests/experimental/ProgrammaticPortsSpec.scala b/src/test/scala/chiselTests/experimental/ProgrammaticPortsSpec.scala deleted file mode 100644 index 64aabb4b..00000000 --- a/src/test/scala/chiselTests/experimental/ProgrammaticPortsSpec.scala +++ /dev/null @@ -1,73 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests -package experimental - -import chisel3._ -import chisel3.stage.ChiselStage - -// NOTE This is currently an experimental API and subject to change -// Example using a private port -class PrivatePort extends NamedModuleTester { - private val port = expectName(IO(Input(UInt(8.W))), "foo") - port.suggestName("foo") -} - -// Example of using composition to add ports to a Module -class CompositionalPort(module: NamedModuleTester, name: String) { - import chisel3.experimental.IO - val foo = module.expectName(IO(Output(Bool())), name) - foo.suggestName(name) - foo := true.B -} - -class CompositionalPortTester extends NamedModuleTester { - val a = new CompositionalPort(this, "cheese") - val b = new CompositionalPort(this, "tart") -} - -class PortsWinTester extends NamedModuleTester { - val wire = expectName(Wire(UInt()), "wire_1") - val foo = expectName(Wire(UInt()).suggestName("wire"), "wire_2") - val output = expectName(IO(Output(UInt())).suggestName("wire"), "wire") -} - -class ProgrammaticPortsSpec extends ChiselFlatSpec with Utils { - - private def doTest(testMod: => NamedModuleTester): Unit = { - var module: NamedModuleTester = null - ChiselStage.elaborate { module = testMod; module } - assert(module.getNameFailures() == Nil) - } - - "Programmatic port creation" should "be supported" in { - doTest(new PrivatePort) - } - - "Calling IO outside of a Module definition" should "be supported" in { - doTest(new CompositionalPortTester) - } - - "Ports" should "always win over internal components in naming" in { - doTest(new PortsWinTester) - } - - "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(clock.suggestName("tart"), "clock") - expectName(reset.suggestName("teser"), "reset") - }) - } - - "SuggestName collisions on ports" should "be illegal" in { - a[ChiselException] should be thrownBy extractCause[ChiselException] { - 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/experimental/TraceSpec.scala b/src/test/scala/chiselTests/experimental/TraceSpec.scala deleted file mode 100644 index 1d67ba0b..00000000 --- a/src/test/scala/chiselTests/experimental/TraceSpec.scala +++ /dev/null @@ -1,328 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests - -import chisel3._ -import chisel3.experimental.Trace._ -import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage, DesignAnnotation} -import chisel3.util.experimental.InlineInstance -import firrtl.AnnotationSeq -import firrtl.annotations.TargetToken.{Instance, OfModule, Ref} -import firrtl.annotations.{CompleteTarget, InstanceTarget, ReferenceTarget} -import org.scalatest.matchers.should.Matchers - -class TraceSpec extends ChiselFlatSpec with Matchers { - - def refTarget(topName: String, ref: String, path: Seq[(Instance, OfModule)] = Seq()) = - ReferenceTarget(topName, topName, path, ref, Seq()) - - def instTarget(topName: String, instance: String, ofModule: String, path: Seq[(Instance, OfModule)] = Seq()) = - InstanceTarget(topName, topName, path, instance, ofModule) - - def compile(testName: String, gen: () => Module): (os.Path, AnnotationSeq) = { - val testDir = os.Path(createTestDirectory(testName).getAbsolutePath) - val annos = (new ChiselStage).execute( - Array("--target-dir", s"$testDir"), - Seq( - ChiselGeneratorAnnotation(gen) - ) - ) - (testDir, annos) - } - - "TraceFromAnnotations" should "be able to get nested name." in { - class Bundle0 extends Bundle { - val a = UInt(8.W) - val b = Bool() - val c = Enum0.Type - } - - class Bundle1 extends Bundle { - val a = new Bundle0 - val b = Vec(4, Vec(4, Bool())) - } - - class Module0 extends Module { - val i = IO(Input(new Bundle1)) - val o = IO(Output(new Bundle1)) - val r = Reg(new Bundle1) - o := r - r := i - - traceName(r) - traceName(i) - traceName(o) - } - - class Module1 extends Module { - val i = IO(Input(new Bundle1)) - val m0 = Module(new Module0) - m0.i := i - m0.o := DontCare - } - - object Enum0 extends ChiselEnum { - val s0, s1, s2 = Value - } - - val (testDir, annos) = compile("TraceFromAnnotaions", () => new Module1) - val dut = annos.collectFirst { case DesignAnnotation(dut) => dut }.get.asInstanceOf[Module1] - // out of Builder. - - val oneTarget = finalTarget(annos)(dut.m0.r.a.a).head - val ioTarget = finalTarget(annos)(dut.m0.i.b(1)(2)).head - - val topName = "Module1" - oneTarget should be(refTarget(topName, "r_a_a", Seq(Instance("m0") -> OfModule("Module0")))) - - ioTarget should be(refTarget(topName, "i_b_1_2", Seq(Instance("m0") -> OfModule("Module0")))) - - // Below codes doesn't needs to be a FIRRTL Transform. - def generateVerilatorConfigFile(data: Seq[Data], annos: AnnotationSeq): String = - """`verilator_config - |lint_off -rule unused - |lint_off -rule declfilename - |""".stripMargin + - data - .flatMap(finalTarget(annos)) - .toSet - .map { target: CompleteTarget => - s"""public_flat_rd -module "${target.tokens.collectFirst { - case OfModule(m) => m - }.get}" -var "${target.tokens.collectFirst { case Ref(r) => r }.get}"""" - } - .mkString("\n") + "\n" - - def verilatorTemplate(data: Seq[Data], annos: AnnotationSeq): String = { - val vpiNames = data.flatMap(finalTarget(annos)).map { ct => - s"""TOP.${ct.circuit}.${ct.path.map { case (Instance(i), _) => i }.mkString(".")}.${ct.tokens.collectFirst { - case Ref(r) => r - }.get}""" - } - s""" - |#include "V${topName}.h" - |#include "verilated_vpi.h" - |#include <memory> - |#include <verilated.h> - | - |int vpiGetInt(const char name[]) { - | vpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8 *)name, NULL); - | if (!vh1) - | vl_fatal(__FILE__, __LINE__, "sim_main", "No handle found"); - | s_vpi_value v; - | v.format = vpiIntVal; - | vpi_get_value(vh1, &v); - | return v.value.integer; - |} - | - |int main(int argc, char **argv) { - | const std::unique_ptr<VerilatedContext> contextp{new VerilatedContext}; - | contextp->commandArgs(argc, argv); - | const std::unique_ptr<V$topName> top{new V$topName{contextp.get(), "TOP"}}; - | top->reset = 0; - | top->clock = 0; - | int a_b = 1; - | top->i_a_b = a_b; - | bool started = false; - | int ticks = 20; - | while (ticks--) { - | contextp->timeInc(1); - | top->clock = !top->clock; - | if (!top->clock) { - | if (contextp->time() > 1 && contextp->time() < 10) { - | top->reset = 1; - | } else { - | top->reset = 0; - | started = true; - | } - | a_b = a_b ? 0 : 1; - | top->i_a_b = a_b; - | } - | top->eval(); - | VerilatedVpi::callValueCbs(); - | if (started && !top->clock) { - | const int i = top->i_a_b; - | const int o = vpiGetInt("${vpiNames.head}"); - | if (i == o) - | vl_fatal(__FILE__, __LINE__, "sim_main", "${vpiNames.head} should be the old value of Module1.i_a_b"); - | printf("${vpiNames.head}=%d Module1.m0.o_a_b=%d\\n", i, o); - | } - | } - | top->final(); - | return 0; - |} - |""".stripMargin - } - - val config = os.temp(dir = testDir, contents = generateVerilatorConfigFile(Seq(dut.m0.o.a.b), annos)) - val verilog = testDir / s"$topName.v" - val cpp = os.temp(dir = testDir, suffix = ".cpp", contents = verilatorTemplate(Seq(dut.m0.o.a.b), annos)) - val exe = testDir / "obj_dir" / s"V$topName" - os.proc("verilator", "-Wall", "--cc", "--exe", "--build", "--vpi", s"$cpp", s"$verilog", s"$config") - .call(stdout = os.Inherit, stderr = os.Inherit, cwd = testDir) - assert( - os.proc(s"$exe").call(stdout = os.Inherit, stderr = os.Inherit).exitCode == 0, - "verilator should exit peacefully" - ) - } - - "TraceFromCollideBundle" should "work" in { - class CollideModule extends Module { - val a = IO( - Input( - Vec( - 2, - new Bundle { - val b = Flipped(Bool()) - val c = Vec( - 2, - new Bundle { - val d = UInt(2.W) - val e = Flipped(UInt(3.W)) - } - ) - val c_1_e = UInt(4.W) - } - ) - ) - ) - val a_0_c = IO(Output(UInt(5.W))) - val a__0 = IO(Output(UInt(5.W))) - a_0_c := DontCare - a__0 := DontCare - - traceName(a) - traceName(a_0_c) - traceName(a__0) - } - - val (_, annos) = compile("TraceFromCollideBundle", () => new CollideModule) - val dut = annos.collectFirst { case DesignAnnotation(dut) => dut }.get.asInstanceOf[CollideModule] - - val topName = "CollideModule" - - val a0 = finalTarget(annos)(dut.a(0)) - val a__0 = finalTarget(annos)(dut.a__0).head - val a__0_ref = refTarget(topName, "a__0") - a0.foreach(_ shouldNot be(a__0_ref)) - a__0 should be(a__0_ref) - - val a0_c = finalTarget(annos)(dut.a(0).c) - val a_0_c = finalTarget(annos)(dut.a_0_c).head - val a_0_c_ref = refTarget(topName, "a_0_c") - a0_c.foreach(_ shouldNot be(a_0_c_ref)) - a_0_c should be(a_0_c_ref) - - val a0_c1_e = finalTarget(annos)(dut.a(0).c(1).e).head - val a0_c_1_e = finalTarget(annos)(dut.a(0).c_1_e).head - a0_c1_e should be(refTarget(topName, "a_0_c__1_e")) - a0_c_1_e should be(refTarget(topName, "a_0_c_1_e")) - } - - "Inline should work" should "work" in { - class Module0 extends Module { - val i = IO(Input(Bool())) - val o = IO(Output(Bool())) - traceName(i) - o := !i - } - - class Module1 extends Module { - val i = IO(Input(Bool())) - val o = IO(Output(Bool())) - val m0 = Module(new Module0 with InlineInstance) - m0.i := i - o := m0.o - } - - val (_, annos) = compile("Inline", () => new Module1) - val dut = annos.collectFirst { case DesignAnnotation(dut) => dut }.get.asInstanceOf[Module1] - - val m0_i = finalTarget(annos)(dut.m0.i).head - m0_i should be(refTarget("Module1", "m0_i")) - } - - "Constant Propagation" should "be turned off by traceName" in { - class Module0 extends Module { - val i = WireDefault(1.U) - val i0 = i + 1.U - val o = IO(Output(UInt(2.W))) - traceName(i0) - o := i0 - } - - val (_, annos) = compile("ConstantProp", () => new Module0) - val dut = annos.collectFirst { case DesignAnnotation(dut) => dut }.get.asInstanceOf[Module0] - - val i0 = finalTarget(annos)(dut.i0).head - i0 should be(refTarget("Module0", "i0")) - } - - "Nested Module" should "work" in { - class Io extends Bundle { - val i = Input(Bool()) - val o = Output(Bool()) - } - - class Not extends Module { - val io = IO(new Io) - io.o := !io.i - } - - class M1 extends Module { - val io = IO(new Io) - val not = Module(new Not) - not.io <> io - } - - class M2 extends Module { - val io = IO(new Io) - val m1 = Module(new M1 with InlineInstance) - val not = Module(new Not) - - m1.io.i := io.i - not.io.i := io.i - - io.o := m1.io.o && not.io.o - } - - class M3 extends Module { - val io = IO(new Io) - val m2 = Module(new M2) - io <> m2.io - traceName(m2.not) - traceName(m2.m1.not) - } - - val (_, annos) = compile("NestedModule", () => new M3) - val m3 = annos.collectFirst { case DesignAnnotation(dut) => dut }.get.asInstanceOf[M3] - - val m2_m1_not = finalTarget(annos)(m3.m2.m1.not).head - val m2_not = finalTarget(annos)(m3.m2.not).head - - m2_m1_not should be(instTarget("M3", "m1_not", "Not", Seq(Instance("m2") -> OfModule("M2")))) - m2_not should be(instTarget("M3", "not", "Not", Seq(Instance("m2") -> OfModule("M2")))) - } - - "All traced signal" should "generate" in { - class M extends Module { - val a = Wire(Bool()) - val b = Wire(Vec(2, Bool())) - a := DontCare - b := DontCare - Seq(a, b).foreach(traceName) - } - val (_, annos) = compile("NestedModule", () => new M) - val dut = annos.collectFirst { case DesignAnnotation(dut) => dut }.get.asInstanceOf[M] - val allTargets = finalTargetMap(annos) - allTargets(dut.a.toAbsoluteTarget) should be(Seq(refTarget("M", "a"))) - allTargets(dut.b.toAbsoluteTarget) should be( - Seq( - refTarget("M", "b_0"), - refTarget("M", "b_1") - ) - ) - allTargets(dut.b(0).toAbsoluteTarget) should be(Seq(refTarget("M", "b_0"))) - allTargets(dut.b(1).toAbsoluteTarget) should be(Seq(refTarget("M", "b_1"))) - } -} diff --git a/src/test/scala/chiselTests/experimental/Tuple.scala b/src/test/scala/chiselTests/experimental/Tuple.scala deleted file mode 100644 index b57766e7..00000000 --- a/src/test/scala/chiselTests/experimental/Tuple.scala +++ /dev/null @@ -1,163 +0,0 @@ -// See LICENSE for license details. - -package chiselTests.experimental - -import chiselTests.ChiselFlatSpec -import chisel3._ -import chisel3.experimental.conversions._ -import chisel3.stage.ChiselStage - -class TupleSpec extends ChiselFlatSpec { - - behavior.of("Tuple") - - it should "enable using Tuple2 like Data" in { - class MyModule extends Module { - val a, b, c, d = IO(Input(UInt(8.W))) - val sel = IO(Input(Bool())) - val y, z = IO(Output(UInt(8.W))) - (y, z) := Mux(sel, (a, b), (c, d)) - } - // Verilog instead of CHIRRTL because the optimizations make it much prettier - val verilog = ChiselStage.emitVerilog(new MyModule) - verilog should include("assign y = sel ? a : c;") - verilog should include("assign z = sel ? b : d;") - } - - it should "support nesting of tuples" in { - class MyModule extends Module { - val a, b, c, d = IO(Input(UInt(8.W))) - val w, x, y, z = IO(Output(UInt(8.W))) - ((w, x), (y, z)) := ((a, b), (c, d)) - } - val chirrtl = ChiselStage.emitChirrtl(new MyModule) - chirrtl should include("w <= a") - chirrtl should include("x <= b") - chirrtl should include("y <= c") - chirrtl should include("z <= d") - } - - it should "enable using Tuple3 like Data" in { - class MyModule extends Module { - val a, b, c = IO(Input(UInt(8.W))) - val f, g, h = IO(Input(UInt(8.W))) - val sel = IO(Input(Bool())) - val v, w, x = IO(Output(UInt(8.W))) - (v, w, x) := Mux(sel, (a, b, c), (f, g, h)) - } - // Verilog instead of CHIRRTL because the optimizations make it much prettier - val verilog = ChiselStage.emitVerilog(new MyModule) - verilog should include("assign v = sel ? a : f;") - verilog should include("assign w = sel ? b : g;") - verilog should include("assign x = sel ? c : h;") - } - - it should "enable using Tuple4 like Data" in { - class MyModule extends Module { - val a, b, c, d = IO(Input(UInt(8.W))) - val f, g, h, i = IO(Input(UInt(8.W))) - val sel = IO(Input(Bool())) - val v, w, x, y = IO(Output(UInt(8.W))) - (v, w, x, y) := Mux(sel, (a, b, c, d), (f, g, h, i)) - } - // Verilog instead of CHIRRTL because the optimizations make it much prettier - val verilog = ChiselStage.emitVerilog(new MyModule) - verilog should include("assign v = sel ? a : f;") - verilog should include("assign w = sel ? b : g;") - verilog should include("assign x = sel ? c : h;") - verilog should include("assign y = sel ? d : i;") - } - - it should "enable using Tuple5 like Data" in { - class MyModule extends Module { - val a0, a1, a2, a3, a4 = IO(Input(UInt(8.W))) - val b0, b1, b2, b3, b4 = IO(Input(UInt(8.W))) - val sel = IO(Input(Bool())) - val z0, z1, z2, z3, z4 = IO(Output(UInt(8.W))) - (z0, z1, z2, z3, z4) := Mux(sel, (a0, a1, a2, a3, a4), (b0, b1, b2, b3, b4)) - } - // Verilog instead of CHIRRTL because the optimizations make it much prettier - val verilog = ChiselStage.emitVerilog(new MyModule) - for (i <- 0 until 5) { - verilog should include(s"assign z$i = sel ? a$i : b$i;") - } - } - - it should "enable using Tuple6 like Data" in { - class MyModule extends Module { - val a0, a1, a2, a3, a4, a5 = IO(Input(UInt(8.W))) - val b0, b1, b2, b3, b4, b5 = IO(Input(UInt(8.W))) - val sel = IO(Input(Bool())) - val z0, z1, z2, z3, z4, z5 = IO(Output(UInt(8.W))) - (z0, z1, z2, z3, z4, z5) := Mux(sel, (a0, a1, a2, a3, a4, a5), (b0, b1, b2, b3, b4, b5)) - } - // Verilog instead of CHIRRTL because the optimizations make it much prettier - val verilog = ChiselStage.emitVerilog(new MyModule) - for (i <- 0 until 6) { - verilog should include(s"assign z$i = sel ? a$i : b$i;") - } - } - - it should "enable using Tuple7 like Data" in { - class MyModule extends Module { - val a0, a1, a2, a3, a4, a5, a6 = IO(Input(UInt(8.W))) - val b0, b1, b2, b3, b4, b5, b6 = IO(Input(UInt(8.W))) - val sel = IO(Input(Bool())) - val z0, z1, z2, z3, z4, z5, z6 = IO(Output(UInt(8.W))) - (z0, z1, z2, z3, z4, z5, z6) := Mux(sel, (a0, a1, a2, a3, a4, a5, a6), (b0, b1, b2, b3, b4, b5, b6)) - } - // Verilog instead of CHIRRTL because the optimizations make it much prettier - val verilog = ChiselStage.emitVerilog(new MyModule) - for (i <- 0 until 7) { - verilog should include(s"assign z$i = sel ? a$i : b$i;") - } - } - - it should "enable using Tuple8 like Data" in { - class MyModule extends Module { - val a0, a1, a2, a3, a4, a5, a6, a7 = IO(Input(UInt(8.W))) - val b0, b1, b2, b3, b4, b5, b6, b7 = IO(Input(UInt(8.W))) - val sel = IO(Input(Bool())) - val z0, z1, z2, z3, z4, z5, z6, z7 = IO(Output(UInt(8.W))) - (z0, z1, z2, z3, z4, z5, z6, z7) := Mux(sel, (a0, a1, a2, a3, a4, a5, a6, a7), (b0, b1, b2, b3, b4, b5, b6, b7)) - } - // Verilog instead of CHIRRTL because the optimizations make it much prettier - val verilog = ChiselStage.emitVerilog(new MyModule) - for (i <- 0 until 8) { - verilog should include(s"assign z$i = sel ? a$i : b$i;") - } - } - - it should "enable using Tuple9 like Data" in { - class MyModule extends Module { - val a0, a1, a2, a3, a4, a5, a6, a7, a8 = IO(Input(UInt(8.W))) - val b0, b1, b2, b3, b4, b5, b6, b7, b8 = IO(Input(UInt(8.W))) - val sel = IO(Input(Bool())) - val z0, z1, z2, z3, z4, z5, z6, z7, z8 = IO(Output(UInt(8.W))) - (z0, z1, z2, z3, z4, z5, z6, z7, z8) := - Mux(sel, (a0, a1, a2, a3, a4, a5, a6, a7, a8), (b0, b1, b2, b3, b4, b5, b6, b7, b8)) - } - // Verilog instead of CHIRRTL because the optimizations make it much prettier - val verilog = ChiselStage.emitVerilog(new MyModule) - for (i <- 0 until 9) { - verilog should include(s"assign z$i = sel ? a$i : b$i;") - } - } - - it should "enable using Tuple10 like Data" in { - class MyModule extends Module { - val a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 = IO(Input(UInt(8.W))) - val b0, b1, b2, b3, b4, b5, b6, b7, b8, b9 = IO(Input(UInt(8.W))) - val sel = IO(Input(Bool())) - val z0, z1, z2, z3, z4, z5, z6, z7, z8, z9 = IO(Output(UInt(8.W))) - (z0, z1, z2, z3, z4, z5, z6, z7, z8, z9) := - Mux(sel, (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9), (b0, b1, b2, b3, b4, b5, b6, b7, b8, b9)) - } - // Verilog instead of CHIRRTL because the optimizations make it much prettier - val verilog = ChiselStage.emitVerilog(new MyModule) - for (i <- 0 until 10) { - verilog should include(s"assign z$i = sel ? a$i : b$i;") - } - } - -} diff --git a/src/test/scala/chiselTests/experimental/hierarchy/Annotations.scala b/src/test/scala/chiselTests/experimental/hierarchy/Annotations.scala deleted file mode 100644 index ec71fe09..00000000 --- a/src/test/scala/chiselTests/experimental/hierarchy/Annotations.scala +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.experimental.hierarchy - -import _root_.firrtl.annotations._ -import chisel3.experimental.{annotate, BaseModule} -import chisel3.{Data, MemBase} -import chisel3.experimental.hierarchy.{Definition, Hierarchy, Instance} - -// These annotations exist purely for testing purposes -private[hierarchy] object Annotations { - case class MarkAnnotation(target: IsMember, tag: String) extends SingleTargetAnnotation[IsMember] { - def duplicate(n: IsMember): Annotation = this.copy(target = n) - } - case class MarkChiselHierarchyAnnotation[B <: BaseModule](d: Hierarchy[B], tag: String, isAbsolute: Boolean) - extends chisel3.experimental.ChiselAnnotation { - def toFirrtl = MarkAnnotation(d.toTarget, tag) - } - case class MarkChiselAnnotation(d: Data, tag: String, isAbsolute: Boolean) - extends chisel3.experimental.ChiselAnnotation { - def toFirrtl = if (isAbsolute) MarkAnnotation(d.toAbsoluteTarget, tag) else MarkAnnotation(d.toTarget, tag) - } - case class MarkChiselMemAnnotation[T <: Data](m: MemBase[T], tag: String, isAbsolute: Boolean) - extends chisel3.experimental.ChiselAnnotation { - def toFirrtl = if (isAbsolute) MarkAnnotation(m.toAbsoluteTarget, tag) else MarkAnnotation(m.toTarget, tag) - } - def mark(d: Data, tag: String): Unit = annotate(MarkChiselAnnotation(d, tag, false)) - def mark[T <: Data](d: MemBase[T], tag: String): Unit = annotate(MarkChiselMemAnnotation(d, tag, false)) - def mark[B <: BaseModule](d: Hierarchy[B], tag: String): Unit = annotate(MarkChiselHierarchyAnnotation(d, tag, true)) - def amark(d: Data, tag: String): Unit = annotate(MarkChiselAnnotation(d, tag, true)) - def amark[B <: BaseModule](d: Hierarchy[B], tag: String): Unit = annotate(MarkChiselHierarchyAnnotation(d, tag, true)) -} diff --git a/src/test/scala/chiselTests/experimental/hierarchy/DefinitionSpec.scala b/src/test/scala/chiselTests/experimental/hierarchy/DefinitionSpec.scala deleted file mode 100644 index 6ff4a3eb..00000000 --- a/src/test/scala/chiselTests/experimental/hierarchy/DefinitionSpec.scala +++ /dev/null @@ -1,599 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests -package experimental.hierarchy - -import chisel3._ -import chisel3.experimental.BaseModule -import chisel3.experimental.hierarchy.{instantiable, public, Definition, Instance} - -// TODO/Notes -// - In backport, clock/reset are not automatically assigned. I think this is fixed in 3.5 -// - CircuitTarget for annotations on the definition are wrong - needs to be fixed. -class DefinitionSpec extends ChiselFunSpec with Utils { - import Annotations._ - import Examples._ - describe("0: Definition instantiation") { - it("0.0: module name of a definition should be correct") { - class Top extends Module { - val definition = Definition(new AddOne) - } - val (chirrtl, _) = getFirrtlAndAnnos(new Top) - chirrtl.serialize should include("module AddOne :") - } - it("0.2: accessing internal fields through non-generated means is hard to do") { - class Top extends Module { - val definition = Definition(new AddOne) - //definition.lookup(_.in) // Uncommenting this line will give the following error: - //"You are trying to access a macro-only API. Please use the @public annotation instead." - definition.in - } - val (chirrtl, _) = getFirrtlAndAnnos(new Top) - chirrtl.serialize should include("module AddOne :") - } - it("0.2: reset inference is not defaulted to Bool for definitions") { - class Top extends Module with RequireAsyncReset { - val definition = Definition(new HasUninferredReset) - val i0 = Instance(definition) - i0.in := 0.U - } - val (chirrtl, _) = getFirrtlAndAnnos(new Top) - chirrtl.serialize should include("inst i0 of HasUninferredReset") - } - it("0.3: module names of repeated definition should be sequential") { - class Top extends Module { - val k = Module( - new AddTwoParameterized( - 4, - (x: Int) => - Seq.tabulate(x) { j => - val addOneDef = Definition(new AddOneParameterized(x + j)) - val addOne = Instance(addOneDef) - addOne - } - ) - ) - } - val (chirrtl, _) = getFirrtlAndAnnos(new Top) - chirrtl.serialize should include("module AddOneParameterized :") - chirrtl.serialize should include("module AddOneParameterized_1 :") - chirrtl.serialize should include("module AddOneParameterized_2 :") - chirrtl.serialize should include("module AddOneParameterized_3 :") - } - it("0.4: multiple instantiations should have sequential names") { - class Top extends Module { - val addOneDef = Definition(new AddOneParameterized(4)) - val addOne = Instance(addOneDef) - val otherAddOne = Module(new AddOneParameterized(4)) - } - val (chirrtl, _) = getFirrtlAndAnnos(new Top) - chirrtl.serialize should include("module AddOneParameterized :") - chirrtl.serialize should include("module AddOneParameterized_1 :") - } - it("0.5: nested definitions should have sequential names") { - class Top extends Module { - val k = Module( - new AddTwoWithNested( - 4, - (x: Int) => - Seq.tabulate(x) { j => - val addOneDef = Definition(new AddOneWithNested(x + j)) - val addOne = Instance(addOneDef) - addOne - } - ) - ) - } - val (chirrtl, _) = getFirrtlAndAnnos(new Top) - chirrtl.serialize should include("module AddOneWithNested :") - chirrtl.serialize should include("module AddOneWithNested_1 :") - chirrtl.serialize should include("module AddOneWithNested_2 :") - chirrtl.serialize should include("module AddOneWithNested_3 :") - } - } - describe("1: Annotations on definitions in same chisel compilation") { - it("1.0: should work on a single definition, annotating the definition") { - class Top extends Module { - val definition: Definition[AddOne] = Definition(new AddOne) - mark(definition, "mark") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddOne".mt, "mark")) - } - it("1.1: should work on a single definition, annotating an inner wire") { - class Top extends Module { - val definition: Definition[AddOne] = Definition(new AddOne) - mark(definition.innerWire, "i0.innerWire") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddOne>innerWire".rt, "i0.innerWire")) - } - it("1.2: should work on a two nested definitions, annotating the definition") { - class Top extends Module { - val definition: Definition[AddTwo] = Definition(new AddTwo) - mark(definition.definition, "i0.i0") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddOne".mt, "i0.i0")) - } - it("1.2: should work on an instance in a definition, annotating the instance") { - class Top extends Module { - val definition: Definition[AddTwo] = Definition(new AddTwo) - mark(definition.i0, "i0.i0") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddTwo/i0:AddOne".it, "i0.i0")) - } - it("1.2: should work on a definition in an instance, annotating the definition") { - class Top extends Module { - val definition: Definition[AddTwo] = Definition(new AddTwo) - val i0 = Instance(definition) - mark(i0.definition, "i0.i0") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddOne".mt, "i0.i0")) - } - it("1.3: should work on a wire in an instance in a definition") { - class Top extends Module { - val definition: Definition[AddTwo] = Definition(new AddTwo) - mark(definition.i0.innerWire, "i0.i0.innerWire") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddTwo/i0:AddOne>innerWire".rt, "i0.i0.innerWire")) - } - it("1.4: should work on a nested module in a definition, annotating the module") { - class Top extends Module { - val definition: Definition[AddTwoMixedModules] = Definition(new AddTwoMixedModules) - mark(definition.i1, "i0.i1") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddTwoMixedModules/i1:AddOne_1".it, "i0.i1")) - } - // Can you define an instantiable container? I think not. - // Instead, we can test the instantiable container in a definition - it("1.5: should work on an instantiable container, annotating a wire in the defintion") { - class Top extends Module { - val definition: Definition[AddOneWithInstantiableWire] = Definition(new AddOneWithInstantiableWire) - mark(definition.wireContainer.innerWire, "i0.innerWire") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddOneWithInstantiableWire>innerWire".rt, "i0.innerWire")) - } - it("1.6: should work on an instantiable container, annotating a module") { - class Top extends Module { - val definition = Definition(new AddOneWithInstantiableModule) - mark(definition.moduleContainer.i0, "i0.i0") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddOneWithInstantiableModule/i0:AddOne".it, "i0.i0")) - } - it("1.7: should work on an instantiable container, annotating an instance") { - class Top extends Module { - val definition = Definition(new AddOneWithInstantiableInstance) - mark(definition.instanceContainer.i0, "i0.i0") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddOneWithInstantiableInstance/i0:AddOne".it, "i0.i0")) - } - it("1.8: should work on an instantiable container, annotating an instantiable container's module") { - class Top extends Module { - val definition = Definition(new AddOneWithInstantiableInstantiable) - mark(definition.containerContainer.container.i0, "i0.i0") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddOneWithInstantiableInstantiable/i0:AddOne".it, "i0.i0")) - } - it("1.9: should work on public member which references public member of another instance") { - class Top extends Module { - val definition = Definition(new AddOneWithInstantiableInstantiable) - mark(definition.containerContainer.container.i0, "i0.i0") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddOneWithInstantiableInstantiable/i0:AddOne".it, "i0.i0")) - } - it("1.10: should work for targets on definition to have correct circuit name") { - class Top extends Module { - val definition = Definition(new AddOneWithAnnotation) - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddOneWithAnnotation>innerWire".rt, "innerWire")) - } - } - describe("2: Annotations on designs not in the same chisel compilation") { - it("2.0: should work on an innerWire, marked in a different compilation") { - val first = elaborateAndGetModule(new AddTwo) - class Top(x: AddTwo) extends Module { - val parent = Definition(new ViewerParent(x, false, true)) - } - val (_, annos) = getFirrtlAndAnnos(new Top(first)) - annos should contain(MarkAnnotation("~AddTwo|AddTwo/i0:AddOne>innerWire".rt, "first")) - } - it("2.1: should work on an innerWire, marked in a different compilation, in instanced instantiable") { - val first = elaborateAndGetModule(new AddTwo) - class Top(x: AddTwo) extends Module { - val parent = Definition(new ViewerParent(x, true, false)) - } - val (_, annos) = getFirrtlAndAnnos(new Top(first)) - annos should contain(MarkAnnotation("~AddTwo|AddTwo/i0:AddOne>innerWire".rt, "second")) - } - it("2.2: should work on an innerWire, marked in a different compilation, in instanced module") { - val first = elaborateAndGetModule(new AddTwo) - class Top(x: AddTwo) extends Module { - val parent = Definition(new ViewerParent(x, false, false)) - mark(parent.viewer.x.i0.innerWire, "third") - } - val (_, annos) = getFirrtlAndAnnos(new Top(first)) - annos should contain(MarkAnnotation("~AddTwo|AddTwo/i0:AddOne>innerWire".rt, "third")) - } - } - describe("3: @public") { - it("3.0: should work on multi-vals") { - class Top() extends Module { - val mv = Definition(new MultiVal()) - mark(mv.x, "mv.x") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|MultiVal>x".rt, "mv.x")) - } - it("3.1: should work on lazy vals") { - class Top() extends Module { - val lv = Definition(new LazyVal()) - mark(lv.x, lv.y) - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|LazyVal>x".rt, "Hi")) - } - it("3.2: should work on islookupables") { - class Top() extends Module { - val p = Parameters("hi", 0) - val up = Definition(new UsesParameters(p)) - mark(up.x, up.y.string + up.y.int) - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|UsesParameters>x".rt, "hi0")) - } - it("3.3: should work on lists") { - class Top() extends Module { - val i = Definition(new HasList()) - mark(i.x(1), i.y(1).toString) - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|HasList>x_1".rt, "2")) - } - it("3.4: should work on seqs") { - class Top() extends Module { - val i = Definition(new HasSeq()) - mark(i.x(1), i.y(1).toString) - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|HasSeq>x_1".rt, "2")) - } - it("3.5: should work on options") { - class Top() extends Module { - val i = Definition(new HasOption()) - i.x.map(x => mark(x, "x")) - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|HasOption>x".rt, "x")) - } - it("3.6: should work on vecs") { - class Top() extends Module { - val i = Definition(new HasVec()) - mark(i.x, "blah") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|HasVec>x".rt, "blah")) - } - it("3.7: should work on statically indexed vectors external to module") { - class Top() extends Module { - val i = Definition(new HasVec()) - mark(i.x(1), "blah") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|HasVec>x[1]".rt, "blah")) - } - it("3.8: should work on statically indexed vectors internal to module") { - class Top() extends Module { - val i = Definition(new HasIndexedVec()) - mark(i.y, "blah") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|HasIndexedVec>x[1]".rt, "blah")) - } - ignore("3.9: should work on vals in constructor arguments") { - class Top() extends Module { - val i = Definition(new HasPublicConstructorArgs(10)) - //mark(i.x, i.int.toString) - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|HasPublicConstructorArgs>x".rt, "10")) - } - it("3.10: should work on unimplemented vals in abstract classes/traits") { - class Top() extends Module { - val i = Definition(new ConcreteHasBlah()) - def f(d: Definition[HasBlah]): Unit = { - mark(d, d.blah.toString) - } - f(i) - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|ConcreteHasBlah".mt, "10")) - } - it("3.11: should work on eithers") { - class Top() extends Module { - val i = Definition(new HasEither()) - i.x.map(x => mark(x, "xright")).left.map(x => mark(x, "xleft")) - i.y.map(x => mark(x, "yright")).left.map(x => mark(x, "yleft")) - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|HasEither>x".rt, "xright")) - annos should contain(MarkAnnotation("~Top|HasEither>y".rt, "yleft")) - } - it("3.12: should work on tuple2") { - class Top() extends Module { - val i = Definition(new HasTuple2()) - mark(i.xy._1, "x") - mark(i.xy._2, "y") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|HasTuple2>x".rt, "x")) - annos should contain(MarkAnnotation("~Top|HasTuple2>y".rt, "y")) - } - it("3.13: should work on Mems/SyncReadMems") { - class Top() extends Module { - val i = Definition(new HasMems()) - mark(i.mem, "Mem") - mark(i.syncReadMem, "SyncReadMem") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|HasMems>mem".rt, "Mem")) - annos should contain(MarkAnnotation("~Top|HasMems>syncReadMem".rt, "SyncReadMem")) - } - it("3.14: should not create memory ports") { - class Top() extends Module { - val i = Definition(new HasMems()) - i.mem(0) := 100.U // should be illegal! - } - val failure = intercept[ChiselException] { - getFirrtlAndAnnos(new Top) - } - assert( - failure.getMessage == - "Cannot create a memory port in a different module (Top) than where the memory is (HasMems)." - ) - } - } - describe("4: toDefinition") { - it("4.0: should work on modules") { - class Top() extends Module { - val i = Module(new AddOne()) - f(i.toDefinition) - } - def f(i: Definition[AddOne]): Unit = mark(i.innerWire, "blah") - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddOne>innerWire".rt, "blah")) - } - it("4.2: should work on seqs of modules") { - class Top() extends Module { - val is = Seq(Module(new AddTwo()), Module(new AddTwo())).map(_.toDefinition) - mark(f(is), "blah") - } - def f(i: Seq[Definition[AddTwo]]): Data = i.head.i0.innerWire - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddTwo/i0:AddOne>innerWire".rt, "blah")) - } - it("4.2: should work on options of modules") { - class Top() extends Module { - val is: Option[Definition[AddTwo]] = Some(Module(new AddTwo())).map(_.toDefinition) - mark(f(is), "blah") - } - def f(i: Option[Definition[AddTwo]]): Data = i.get.i0.innerWire - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddTwo/i0:AddOne>innerWire".rt, "blah")) - } - } - describe("5: Absolute Targets should work as expected") { - it("5.0: toAbsoluteTarget on a port of a definition") { - class Top() extends Module { - val i = Definition(new AddTwo()) - amark(i.in, "blah") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddTwo>in".rt, "blah")) - } - it("5.1: toAbsoluteTarget on a subinstance's data within a definition") { - class Top() extends Module { - val i = Definition(new AddTwo()) - amark(i.i0.innerWire, "blah") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddTwo/i0:AddOne>innerWire".rt, "blah")) - } - it("5.2: toAbsoluteTarget on a submodule's data within a definition") { - class Top() extends Module { - val i = Definition(new AddTwoMixedModules()) - amark(i.i1.in, "blah") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddTwoMixedModules/i1:AddOne_1>in".rt, "blah")) - } - it("5.3: toAbsoluteTarget on a submodule's data, in an aggregate, within a definition") { - class Top() extends Module { - val i = Definition(new InstantiatesHasVec()) - amark(i.i1.x.head, "blah") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|InstantiatesHasVec/i1:HasVec_1>x[0]".rt, "blah")) - } - } - describe("6: @instantiable traits should work as expected") { - class MyBundle extends Bundle { - val in = Input(UInt(8.W)) - val out = Output(UInt(8.W)) - } - @instantiable - trait ModuleIntf extends BaseModule { - @public val io = IO(new MyBundle) - } - @instantiable - class ModuleWithCommonIntf(suffix: String = "") extends Module with ModuleIntf { - override def desiredName: String = super.desiredName + suffix - @public val sum = io.in + 1.U - - io.out := sum - } - class BlackBoxWithCommonIntf extends BlackBox with ModuleIntf - - it("6.0: A Module that implements an @instantiable trait should be definable as that trait") { - class Top extends Module { - val i: Definition[ModuleIntf] = Definition(new ModuleWithCommonIntf) - mark(i.io.in, "gotcha") - mark(i, "inst") - } - val expected = List( - "~Top|ModuleWithCommonIntf>io.in".rt -> "gotcha", - "~Top|ModuleWithCommonIntf".mt -> "inst" - ) - val (chirrtl, annos) = getFirrtlAndAnnos(new Top) - for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain(e) - } - } - it( - "6.1 An @instantiable Module that implements an @instantiable trait should be able to use extension methods from both" - ) { - class Top extends Module { - val i: Definition[ModuleWithCommonIntf] = Definition(new ModuleWithCommonIntf) - mark(i.io.in, "gotcha") - mark(i.sum, "also this") - mark(i, "inst") - } - val expected = List( - "~Top|ModuleWithCommonIntf>io.in".rt -> "gotcha", - "~Top|ModuleWithCommonIntf>sum".rt -> "also this", - "~Top|ModuleWithCommonIntf".mt -> "inst" - ) - val (chirrtl, annos) = getFirrtlAndAnnos(new Top) - for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain(e) - } - } - it("6.2 A BlackBox that implements an @instantiable trait should be instantiable as that trait") { - class Top extends Module { - val m: ModuleIntf = Module(new BlackBoxWithCommonIntf) - val d: Definition[ModuleIntf] = m.toDefinition - mark(d.io.in, "gotcha") - mark(d, "module") - } - val expected = List( - "~Top|BlackBoxWithCommonIntf>in".rt -> "gotcha", - "~Top|BlackBoxWithCommonIntf".mt -> "module" - ) - val (chirrtl, annos) = getFirrtlAndAnnos(new Top) - for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain(e) - } - } - it("6.3 It should be possible to have Vectors of @instantiable traits mixing concrete subclasses") { - class Top extends Module { - val definition = Definition(new ModuleWithCommonIntf("X")) - val insts: Seq[Definition[ModuleIntf]] = Vector( - Module(new ModuleWithCommonIntf("Y")).toDefinition, - Module(new BlackBoxWithCommonIntf).toDefinition, - definition - ) - mark(insts(0).io.in, "foo") - mark(insts(1).io.in, "bar") - mark(insts(2).io.in, "fizz") - } - val expected = List( - "~Top|ModuleWithCommonIntfY>io.in".rt -> "foo", - "~Top|BlackBoxWithCommonIntf>in".rt -> "bar", - "~Top|ModuleWithCommonIntfX>io.in".rt -> "fizz" - ) - val (chirrtl, annos) = getFirrtlAndAnnos(new Top) - for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain(e) - } - } - } - describe("7: @instantiable and @public should compose with DataView") { - import chisel3.experimental.dataview._ - ignore("7.0: should work on simple Views") { - @instantiable - class MyModule extends RawModule { - val in = IO(Input(UInt(8.W))) - @public val out = IO(Output(UInt(8.W))) - val sum = in + 1.U - out := sum + 1.U - @public val foo = in.viewAs[UInt] - @public val bar = sum.viewAs[UInt] - } - class Top extends RawModule { - val foo = IO(Input(UInt(8.W))) - val bar = IO(Output(UInt(8.W))) - val d = Definition(new MyModule) - val i = Instance(d) - i.foo := foo - bar := i.out - mark(d.out, "out") - mark(d.foo, "foo") - mark(d.bar, "bar") - } - val expectedAnnos = List( - "~Top|MyModule>out".rt -> "out", - "~Top|MyModule>in".rt -> "foo", - "~Top|MyModule>sum".rt -> "bar" - ) - val expectedLines = List( - "i.in <= foo", - "bar <= i.out" - ) - val (chirrtl, annos) = getFirrtlAndAnnos(new Top) - val text = chirrtl.serialize - for (line <- expectedLines) { - text should include(line) - } - for (e <- expectedAnnos.map(MarkAnnotation.tupled)) { - annos should contain(e) - } - } - ignore("7.1: should work on Aggregate Views that are mapped 1:1") { - import chiselTests.experimental.SimpleBundleDataView._ - @instantiable - class MyModule extends RawModule { - private val a = IO(Input(new BundleA(8))) - private val b = IO(Output(new BundleA(8))) - @public val in = a.viewAs[BundleB] - @public val out = b.viewAs[BundleB] - out := in - } - class Top extends RawModule { - val foo = IO(Input(new BundleB(8))) - val bar = IO(Output(new BundleB(8))) - val d = Definition(new MyModule) - val i = Instance(d) - i.in := foo - bar.bar := i.out.bar - mark(d.in, "in") - mark(d.in.bar, "in_bar") - } - val expectedAnnos = List( - "~Top|MyModule>a".rt -> "in", - "~Top|MyModule>a.foo".rt -> "in_bar" - ) - val expectedLines = List( - "i.a <= foo", - "bar <= i.b.foo" - ) - val (chirrtl, annos) = getFirrtlAndAnnos(new Top) - val text = chirrtl.serialize - for (line <- expectedLines) { - text should include(line) - } - for (e <- expectedAnnos.map(MarkAnnotation.tupled)) { - annos should contain(e) - } - } - } -} diff --git a/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala b/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala deleted file mode 100644 index 27725c49..00000000 --- a/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala +++ /dev/null @@ -1,340 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.experimental.hierarchy - -import chisel3._ -import chisel3.util.Valid -import chisel3.experimental.hierarchy._ -import chisel3.experimental.BaseModule - -object Examples { - import Annotations._ - @instantiable - class AddOne extends Module { - @public val in = IO(Input(UInt(32.W))) - @public val out = IO(Output(UInt(32.W))) - @public val innerWire = Wire(UInt(32.W)) - innerWire := in + 1.U - out := innerWire - } - @instantiable - class AddOneWithAnnotation extends Module { - @public val in = IO(Input(UInt(32.W))) - @public val out = IO(Output(UInt(32.W))) - @public val innerWire = Wire(UInt(32.W)) - mark(innerWire, "innerWire") - innerWire := in + 1.U - out := innerWire - } - @instantiable - class AddOneWithAbsoluteAnnotation extends Module { - @public val in = IO(Input(UInt(32.W))) - @public val out = IO(Output(UInt(32.W))) - @public val innerWire = Wire(UInt(32.W)) - amark(innerWire, "innerWire") - innerWire := in + 1.U - out := innerWire - } - @instantiable - class AddOneParameterized(width: Int) extends Module { - @public val in = IO(Input(UInt(width.W))) - @public val out = IO(Output(UInt(width.W))) - out := in + 1.U - } - class AddOneWithNested(width: Int) extends Module { - @public val in = IO(Input(UInt(width.W))) - @public val out = IO(Output(UInt(width.W))) - val addOneDef = Seq.fill(3)(Definition(new AddOne)) - out := in + 1.U - } - @instantiable - class AddOneBlackBox extends BlackBox { - @public val io = IO(new Bundle { - val in = Input(UInt(32.W)) - val out = Output(UInt(32.W)) - }) - } - - @instantiable - class AddTwo extends Module { - @public val in = IO(Input(UInt(32.W))) - @public val out = IO(Output(UInt(32.W))) - @public val definition = Definition(new AddOne) - @public val i0: Instance[AddOne] = Instance(definition) - @public val i1: Instance[AddOne] = Instance(definition) - i0.in := in - i1.in := i0.out - out := i1.out - } - @instantiable - class AddTwoMixedModules extends Module { - @public val in = IO(Input(UInt(32.W))) - @public val out = IO(Output(UInt(32.W))) - val definition = Definition(new AddOne) - @public val i0: Instance[AddOne] = Instance(definition) - @public val i1 = Module(new AddOne) - i0.in := in - i1.in := i0.out - out := i1.out - } - @instantiable - class AddTwoParameterized(width: Int, makeParameterizedOnes: Int => Seq[Instance[AddOneParameterized]]) - extends Module { - val in = IO(Input(UInt(width.W))) - val out = IO(Output(UInt(width.W))) - val addOnes = makeParameterizedOnes(width) - addOnes.head.in := in - out := addOnes.last.out - addOnes.zip(addOnes.tail).foreach { case (head, tail) => tail.in := head.out } - } - @instantiable - class AddTwoWithNested(width: Int, makeParameterizedOnes: Int => Seq[Instance[AddOneWithNested]]) extends Module { - val in = IO(Input(UInt(width.W))) - val out = IO(Output(UInt(width.W))) - val addOnes = makeParameterizedOnes(width) - } - - @instantiable - class AddFour extends Module { - @public val in = IO(Input(UInt(32.W))) - @public val out = IO(Output(UInt(32.W))) - @public val definition = Definition(new AddTwoMixedModules) - @public val i0 = Instance(definition) - @public val i1 = Instance(definition) - i0.in := in - i1.in := i0.out - out := i1.out - } - @instantiable - class AggregatePortModule extends Module { - @public val io = IO(new Bundle { - val in = Input(UInt(32.W)) - val out = Output(UInt(32.W)) - }) - io.out := io.in - } - @instantiable - class WireContainer { - @public val innerWire = Wire(UInt(32.W)) - } - @instantiable - class AddOneWithInstantiableWire extends Module { - @public val in = IO(Input(UInt(32.W))) - @public val out = IO(Output(UInt(32.W))) - @public val wireContainer = new WireContainer() - wireContainer.innerWire := in + 1.U - out := wireContainer.innerWire - } - @instantiable - class AddOneContainer { - @public val i0 = Module(new AddOne) - } - @instantiable - class AddOneWithInstantiableModule extends Module { - @public val in = IO(Input(UInt(32.W))) - @public val out = IO(Output(UInt(32.W))) - @public val moduleContainer = new AddOneContainer() - moduleContainer.i0.in := in - out := moduleContainer.i0.out - } - @instantiable - class AddOneInstanceContainer { - val definition = Definition(new AddOne) - @public val i0 = Instance(definition) - } - @instantiable - class AddOneWithInstantiableInstance extends Module { - @public val in = IO(Input(UInt(32.W))) - @public val out = IO(Output(UInt(32.W))) - @public val instanceContainer = new AddOneInstanceContainer() - instanceContainer.i0.in := in - out := instanceContainer.i0.out - } - @instantiable - class AddOneContainerContainer { - @public val container = new AddOneContainer - } - @instantiable - class AddOneWithInstantiableInstantiable extends Module { - @public val in = IO(Input(UInt(32.W))) - @public val out = IO(Output(UInt(32.W))) - @public val containerContainer = new AddOneContainerContainer() - containerContainer.container.i0.in := in - out := containerContainer.container.i0.out - } - @instantiable - class Viewer(val y: AddTwo, markPlease: Boolean) { - @public val x = y - if (markPlease) mark(x.i0.innerWire, "first") - } - @instantiable - class ViewerParent(val x: AddTwo, markHere: Boolean, markThere: Boolean) extends Module { - @public val viewer = new Viewer(x, markThere) - if (markHere) mark(viewer.x.i0.innerWire, "second") - } - @instantiable - class MultiVal() extends Module { - @public val (x, y) = (Wire(UInt(3.W)), Wire(UInt(3.W))) - } - @instantiable - class LazyVal() extends Module { - @public val x = Wire(UInt(3.W)) - @public lazy val y = "Hi" - } - case class Parameters(string: String, int: Int) extends IsLookupable - @instantiable - class UsesParameters(p: Parameters) extends Module { - @public val y = p - @public val x = Wire(UInt(3.W)) - } - @instantiable - class HasList() extends Module { - @public val y = List(1, 2, 3) - @public val x = List.fill(3)(Wire(UInt(3.W))) - } - @instantiable - class HasSeq() extends Module { - @public val y = Seq(1, 2, 3) - @public val x = Seq.fill(3)(Wire(UInt(3.W))) - } - @instantiable - class HasOption() extends Module { - @public val x: Option[UInt] = Some(Wire(UInt(3.W))) - } - @instantiable - class HasEither() extends Module { - @public val x: Either[Bool, UInt] = Right(Wire(UInt(3.W)).suggestName("x")) - @public val y: Either[Bool, UInt] = Left(Wire(Bool()).suggestName("y")) - } - @instantiable - class HasTuple2() extends Module { - val x = Wire(UInt(3.W)) - val y = Wire(Bool()) - @public val xy = (x, y) - } - @instantiable - class HasVec() extends Module { - @public val x = VecInit(1.U, 2.U, 3.U) - } - @instantiable - class HasIndexedVec() extends Module { - val x = VecInit(1.U, 2.U, 3.U) - @public val y = x(1) - } - @instantiable - class HasSubFieldAccess extends Module { - val in = IO(Input(Valid(UInt(8.W)))) - @public val valid = in.valid - @public val bits = in.bits - } - @instantiable - class HasPublicConstructorArgs(@public val int: Int) extends Module { - @public val x = Wire(UInt(3.W)) - } - @instantiable - class InstantiatesHasVec() extends Module { - @public val i0 = Instance(Definition(new HasVec())) - @public val i1 = Module(new HasVec()) - } - @instantiable - class HasUninferredReset() extends Module { - @public val in = IO(Input(UInt(3.W))) - @public val out = IO(Output(UInt(3.W))) - out := RegNext(in) - } - @instantiable - abstract class HasBlah() extends Module { - @public val blah: Int - } - - @instantiable - class ConcreteHasBlah() extends HasBlah { - val blah = 10 - } - @instantiable - class HasTypeParams[D <: Data](d: D) extends Module { - @public val blah = Wire(d) - } - - @instantiable - class HasMultipleTypeParamsInside extends Module { - val tpDef0 = Definition(new HasTypeParams(Bool())) - val tpDef1 = Definition(new HasTypeParams(UInt(4.W))) - val i00 = Instance(tpDef0) - val i01 = Instance(tpDef0) - val i10 = Instance(tpDef1) - val i11 = Instance(tpDef1) - } - - @instantiable - class HasMems() extends Module { - @public val mem = Mem(8, UInt(32.W)) - @public val syncReadMem = SyncReadMem(8, UInt(32.W)) - } - - @instantiable - class LeafInstantiable(val bundle: Data) { - @public val bundle = bundle - } - - @instantiable - class NestedInstantiable(val in: LeafInstantiable, val out: LeafInstantiable) { - @public val in = in - @public val out = out - } - - @instantiable - class AddOneNestedInstantiableData(width: Int) extends Module { - @public val in = IO(Input(UInt(width.W))) - @public val out = IO(Output(UInt(width.W))) - out := in + 1.U - - @public val leafOut = new LeafInstantiable(out) - @public val leafIn = new LeafInstantiable(in) - @public val nested = new NestedInstantiable(in = leafIn, out = leafOut) - - } - - class AddTwoNestedInstantiableData(width: Int) extends Module { - val in = IO(Input(UInt(width.W))) - val out = IO(Output(UInt(width.W))) - val addOneDef = Definition(new AddOneNestedInstantiableData(width)) - val i0 = Instance(addOneDef) - val i1 = Instance(addOneDef) - i0.in := in - i1.in := i0.out - out := i1.out - - // both are equivalent to the above - i1.leafIn.bundle := i0.leafOut.bundle - i1.nested.in.bundle := i0.nested.out.bundle - } - - class AddTwoNestedInstantiableDataSubmodule(addOneDef: Definition[AddOneNestedInstantiableData]) extends Module { - val in = IO(Input(UInt(addOneDef.in.getWidth.W))) - val out = IO(Output(UInt(addOneDef.out.getWidth.W))) - val i0 = Instance(addOneDef) - val i1 = Instance(addOneDef) - i0.in := in - i1.in := i0.out - out := i1.out - - // both are equivalent to the above - i1.leafIn.bundle := i0.leafOut.bundle - i1.nested.in.bundle := i0.nested.out.bundle - } - - class AddTwoNestedInstantiableDataWrapper(width: Int) extends Module { - val in = IO(Input(UInt(width.W))) - val out = IO(Output(UInt(width.W))) - - val original = Module(new AddOneNestedInstantiableData(width)) - val copy = Module(new AddTwoNestedInstantiableDataSubmodule(original.toDefinition)) - - original.in := in - copy.in := original.out - out := copy.out - - } - -} diff --git a/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala b/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala deleted file mode 100644 index 6596cd51..00000000 --- a/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala +++ /dev/null @@ -1,1146 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests -package experimental.hierarchy - -import chisel3._ -import chisel3.experimental.BaseModule -import chisel3.experimental.hierarchy.{instantiable, public, Definition, Instance} -import chisel3.util.{DecoupledIO, Valid} - -// TODO/Notes -// - In backport, clock/reset are not automatically assigned. I think this is fixed in 3.5 -// - CircuitTarget for annotations on the definition are wrong - needs to be fixed. -class InstanceSpec extends ChiselFunSpec with Utils { - import Annotations._ - import Examples._ - describe("0: Instance instantiation") { - it("0.0: name of an instance should be correct") { - class Top extends Module { - val definition = Definition(new AddOne) - val i0 = Instance(definition) - } - val (chirrtl, _) = getFirrtlAndAnnos(new Top) - chirrtl.serialize should include("inst i0 of AddOne") - } - it("0.1: name of an instanceclone should not error") { - class Top extends Module { - val definition = Definition(new AddTwo) - val i0 = Instance(definition) - val i = i0.i0 // This should not error - } - val (chirrtl, _) = getFirrtlAndAnnos(new Top) - chirrtl.serialize should include("inst i0 of AddTwo") - } - it("0.2: accessing internal fields through non-generated means is hard to do") { - class Top extends Module { - val definition = Definition(new AddOne) - val i0 = Instance(definition) - //i0.lookup(_.in) // Uncommenting this line will give the following error: - //"You are trying to access a macro-only API. Please use the @public annotation instead." - i0.in - } - val (chirrtl, _) = getFirrtlAndAnnos(new Top) - chirrtl.serialize should include("inst i0 of AddOne") - } - it("0.3: BlackBoxes should be supported") { - class Top extends Module { - val in = IO(Input(UInt(32.W))) - val out = IO(Output(UInt(32.W))) - val io = IO(new Bundle { - val in = Input(UInt(32.W)) - val out = Output(UInt(32.W)) - }) - val definition = Definition(new AddOneBlackBox) - val i0 = Instance(definition) - val i1 = Instance(definition) - i0.io.in := in - out := i0.io.out - io <> i1.io - } - val chirrtl = getFirrtlAndAnnos(new Top)._1.serialize - chirrtl should include("inst i0 of AddOneBlackBox") - chirrtl should include("inst i1 of AddOneBlackBox") - chirrtl should include("i0.in <= in") - chirrtl should include("out <= i0.out") - chirrtl should include("i1.in <= io.in") - chirrtl should include("io.out <= i1.out") - } - } - describe("1: Annotations on instances in same chisel compilation") { - it("1.0: should work on a single instance, annotating the instance") { - class Top extends Module { - val definition: Definition[AddOne] = Definition(new AddOne) - val i0: Instance[AddOne] = Instance(definition) - mark(i0, "i0") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i0:AddOne".it, "i0")) - } - it("1.1: should work on a single instance, annotating an inner wire") { - class Top extends Module { - val definition: Definition[AddOne] = Definition(new AddOne) - val i0: Instance[AddOne] = Instance(definition) - mark(i0.innerWire, "i0.innerWire") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i0:AddOne>innerWire".rt, "i0.innerWire")) - } - it("1.2: should work on a two nested instances, annotating the instance") { - class Top extends Module { - val definition: Definition[AddTwo] = Definition(new AddTwo) - val i0: Instance[AddTwo] = Instance(definition) - mark(i0.i0, "i0.i0") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i0:AddTwo/i0:AddOne".it, "i0.i0")) - } - it("1.3: should work on a two nested instances, annotating the inner wire") { - class Top extends Module { - val definition: Definition[AddTwo] = Definition(new AddTwo) - val i0: Instance[AddTwo] = Instance(definition) - mark(i0.i0.innerWire, "i0.i0.innerWire") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i0:AddTwo/i0:AddOne>innerWire".rt, "i0.i0.innerWire")) - } - it("1.4: should work on a nested module in an instance, annotating the module") { - class Top extends Module { - val definition: Definition[AddTwoMixedModules] = Definition(new AddTwoMixedModules) - val i0: Instance[AddTwoMixedModules] = Instance(definition) - mark(i0.i1, "i0.i1") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i0:AddTwoMixedModules/i1:AddOne_1".it, "i0.i1")) - } - it("1.5: should work on an instantiable container, annotating a wire") { - class Top extends Module { - val definition: Definition[AddOneWithInstantiableWire] = Definition(new AddOneWithInstantiableWire) - val i0: Instance[AddOneWithInstantiableWire] = Instance(definition) - mark(i0.wireContainer.innerWire, "i0.innerWire") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i0:AddOneWithInstantiableWire>innerWire".rt, "i0.innerWire")) - } - it("1.6: should work on an instantiable container, annotating a module") { - class Top extends Module { - val definition = Definition(new AddOneWithInstantiableModule) - val i0 = Instance(definition) - mark(i0.moduleContainer.i0, "i0.i0") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i0:AddOneWithInstantiableModule/i0:AddOne".it, "i0.i0")) - } - it("1.7: should work on an instantiable container, annotating an instance") { - class Top extends Module { - val definition = Definition(new AddOneWithInstantiableInstance) - val i0 = Instance(definition) - mark(i0.instanceContainer.i0, "i0.i0") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i0:AddOneWithInstantiableInstance/i0:AddOne".it, "i0.i0")) - } - it("1.8: should work on an instantiable container, annotating an instantiable container's module") { - class Top extends Module { - val definition = Definition(new AddOneWithInstantiableInstantiable) - val i0 = Instance(definition) - mark(i0.containerContainer.container.i0, "i0.i0") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i0:AddOneWithInstantiableInstantiable/i0:AddOne".it, "i0.i0")) - } - it("1.9: should work on public member which references public member of another instance") { - class Top extends Module { - val definition = Definition(new AddOneWithInstantiableInstantiable) - val i0 = Instance(definition) - mark(i0.containerContainer.container.i0, "i0.i0") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i0:AddOneWithInstantiableInstantiable/i0:AddOne".it, "i0.i0")) - } - it("1.10: should work for targets on definition to have correct circuit name") { - class Top extends Module { - val definition = Definition(new AddOneWithAnnotation) - val i0 = Instance(definition) - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddOneWithAnnotation>innerWire".rt, "innerWire")) - } - it("1.11: should work on things with type parameters") { - class Top extends Module { - val definition = Definition(new HasTypeParams[UInt](UInt(3.W))) - val i0 = Instance(definition) - mark(i0.blah, "blah") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i0:HasTypeParams>blah".rt, "blah")) - } - } - describe("2: Annotations on designs not in the same chisel compilation") { - it("2.0: should work on an innerWire, marked in a different compilation") { - val first = elaborateAndGetModule(new AddTwo) - class Top(x: AddTwo) extends Module { - val parent = Instance(Definition(new ViewerParent(x, false, true))) - } - val (_, annos) = getFirrtlAndAnnos(new Top(first)) - annos should contain(MarkAnnotation("~AddTwo|AddTwo/i0:AddOne>innerWire".rt, "first")) - } - it("2.1: should work on an innerWire, marked in a different compilation, in instanced instantiable") { - val first = elaborateAndGetModule(new AddTwo) - class Top(x: AddTwo) extends Module { - val parent = Instance(Definition(new ViewerParent(x, true, false))) - } - val (_, annos) = getFirrtlAndAnnos(new Top(first)) - annos should contain(MarkAnnotation("~AddTwo|AddTwo/i0:AddOne>innerWire".rt, "second")) - } - it("2.2: should work on an innerWire, marked in a different compilation, in instanced module") { - val first = elaborateAndGetModule(new AddTwo) - class Top(x: AddTwo) extends Module { - val parent = Instance(Definition(new ViewerParent(x, false, false))) - mark(parent.viewer.x.i0.innerWire, "third") - } - val (_, annos) = getFirrtlAndAnnos(new Top(first)) - annos should contain(MarkAnnotation("~AddTwo|AddTwo/i0:AddOne>innerWire".rt, "third")) - } - } - describe("3: @public") { - it("3.0: should work on multi-vals") { - class Top() extends Module { - val mv = Instance(Definition(new MultiVal())) - mark(mv.x, "mv.x") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/mv:MultiVal>x".rt, "mv.x")) - } - it("3.1: should work on lazy vals") { - class Top() extends Module { - val lv = Instance(Definition(new LazyVal())) - mark(lv.x, lv.y) - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/lv:LazyVal>x".rt, "Hi")) - } - it("3.2: should work on islookupables") { - class Top() extends Module { - val p = Parameters("hi", 0) - val up = Instance(Definition(new UsesParameters(p))) - mark(up.x, up.y.string + up.y.int) - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/up:UsesParameters>x".rt, "hi0")) - } - it("3.3: should work on lists") { - class Top() extends Module { - val i = Instance(Definition(new HasList())) - mark(i.x(1), i.y(1).toString) - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i:HasList>x_1".rt, "2")) - } - it("3.4: should work on seqs") { - class Top() extends Module { - val i = Instance(Definition(new HasSeq())) - mark(i.x(1), i.y(1).toString) - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i:HasSeq>x_1".rt, "2")) - } - it("3.5: should work on options") { - class Top() extends Module { - val i = Instance(Definition(new HasOption())) - i.x.map(x => mark(x, "x")) - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i:HasOption>x".rt, "x")) - } - it("3.6: should work on vecs") { - class Top() extends Module { - val i = Instance(Definition(new HasVec())) - mark(i.x, "blah") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i:HasVec>x".rt, "blah")) - } - it("3.7: should work on statically indexed vectors external to module") { - class Top() extends Module { - val i = Instance(Definition(new HasVec())) - mark(i.x(1), "blah") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i:HasVec>x[1]".rt, "blah")) - } - it("3.8: should work on statically indexed vectors internal to module") { - class Top() extends Module { - val i = Instance(Definition(new HasIndexedVec())) - mark(i.y, "blah") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i:HasIndexedVec>x[1]".rt, "blah")) - } - it("3.9: should work on accessed subfields of aggregate ports") { - class Top extends Module { - val input = IO(Input(Valid(UInt(8.W)))) - val i = Instance(Definition(new HasSubFieldAccess)) - i.valid := input.valid - i.bits := input.bits - mark(i.valid, "valid") - mark(i.bits, "bits") - } - val expected = List( - "~Top|Top/i:HasSubFieldAccess>in.valid".rt -> "valid", - "~Top|Top/i:HasSubFieldAccess>in.bits".rt -> "bits" - ) - val lines = List( - "i.in.valid <= input.valid", - "i.in.bits <= input.bits" - ) - val (chirrtl, annos) = getFirrtlAndAnnos(new Top) - val text = chirrtl.serialize - for (line <- lines) { - text should include(line) - } - for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain(e) - } - } - ignore("3.10: should work on vals in constructor arguments") { - class Top() extends Module { - val i = Instance(Definition(new HasPublicConstructorArgs(10))) - //mark(i.x, i.int.toString) - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i:HasPublicConstructorArgs>x".rt, "10")) - } - it("3.11: should work on eithers") { - class Top() extends Module { - val i = Instance(Definition(new HasEither())) - i.x.map(x => mark(x, "xright")).left.map(x => mark(x, "xleft")) - i.y.map(x => mark(x, "yright")).left.map(x => mark(x, "yleft")) - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i:HasEither>x".rt, "xright")) - annos should contain(MarkAnnotation("~Top|Top/i:HasEither>y".rt, "yleft")) - } - it("3.12: should work on tuple2") { - class Top() extends Module { - val i = Instance(Definition(new HasTuple2())) - mark(i.xy._1, "x") - mark(i.xy._2, "y") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i:HasTuple2>x".rt, "x")) - annos should contain(MarkAnnotation("~Top|Top/i:HasTuple2>y".rt, "y")) - } - - it("3.13: should properly support val modifiers") { - class SupClass extends Module { - val value = 10 - val overriddenVal = 10 - } - trait SupTrait { - def x: Int - def y: Int - } - @instantiable class SubClass() extends SupClass with SupTrait { - // This errors - //@public private val privateVal = 10 - // This errors - //@public protected val protectedVal = 10 - @public override val overriddenVal = 12 - @public final val finalVal = 12 - @public lazy val lazyValue = 12 - @public val value = value - @public final override lazy val x: Int = 3 - @public override final lazy val y: Int = 4 - } - } - it("3.13: should work with Mems/SyncReadMems") { - class Top() extends Module { - val i = Instance(Definition(new HasMems())) - mark(i.mem, "Mem") - mark(i.syncReadMem, "SyncReadMem") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i:HasMems>mem".rt, "Mem")) - annos should contain(MarkAnnotation("~Top|Top/i:HasMems>syncReadMem".rt, "SyncReadMem")) - } - it("(3.p): should make connectable IOs on nested IsInstantiables that have IO Datas in them") { - val (chirrtl, _) = getFirrtlAndAnnos(new AddTwoNestedInstantiableData(4)) - exactly(3, chirrtl.serialize.split('\n')) should include("i1.in <= i0.out") - } - it( - "(3.q): should make connectable IOs on nested IsInstantiables's Data when the Instance and Definition do not have the same parent" - ) { - val (chirrtl, _) = getFirrtlAndAnnos(new AddTwoNestedInstantiableDataWrapper(4)) - exactly(3, chirrtl.serialize.split('\n')) should include("i1.in <= i0.out") - } - } - describe("4: toInstance") { - it("4.0: should work on modules") { - class Top() extends Module { - val i = Module(new AddOne()) - f(i.toInstance) - } - def f(i: Instance[AddOne]): Unit = mark(i.innerWire, "blah") - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddOne>innerWire".rt, "blah")) - } - it("4.1: should work on isinstantiables") { - class Top() extends Module { - val i = Module(new AddTwo()) - val v = new Viewer(i, false) - mark(f(v.toInstance), "blah") - } - def f(i: Instance[Viewer]): Data = i.x.i0.innerWire - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddTwo/i0:AddOne>innerWire".rt, "blah")) - } - it("4.2: should work on seqs of modules") { - class Top() extends Module { - val is = Seq(Module(new AddTwo()), Module(new AddTwo())).map(_.toInstance) - mark(f(is), "blah") - } - def f(i: Seq[Instance[AddTwo]]): Data = i.head.i0.innerWire - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddTwo/i0:AddOne>innerWire".rt, "blah")) - } - it("4.3: should work on seqs of isInstantiables") { - class Top() extends Module { - val i = Module(new AddTwo()) - val vs = Seq(new Viewer(i, false), new Viewer(i, false)).map(_.toInstance) - mark(f(vs), "blah") - } - def f(i: Seq[Instance[Viewer]]): Data = i.head.x.i0.innerWire - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddTwo/i0:AddOne>innerWire".rt, "blah")) - } - it("4.2: should work on options of modules") { - class Top() extends Module { - val is: Option[Instance[AddTwo]] = Some(Module(new AddTwo())).map(_.toInstance) - mark(f(is), "blah") - } - def f(i: Option[Instance[AddTwo]]): Data = i.get.i0.innerWire - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddTwo/i0:AddOne>innerWire".rt, "blah")) - } - } - describe("5: Absolute Targets should work as expected") { - it("5.0: toAbsoluteTarget on a port of an instance") { - class Top() extends Module { - val i = Instance(Definition(new AddTwo())) - amark(i.in, "blah") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i:AddTwo>in".rt, "blah")) - } - it("5.1: toAbsoluteTarget on a subinstance's data within an instance") { - class Top() extends Module { - val i = Instance(Definition(new AddTwo())) - amark(i.i0.innerWire, "blah") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i:AddTwo/i0:AddOne>innerWire".rt, "blah")) - } - it("5.2: toAbsoluteTarget on a submodule's data within an instance") { - class Top() extends Module { - val i = Instance(Definition(new AddTwoMixedModules())) - amark(i.i1.in, "blah") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i:AddTwoMixedModules/i1:AddOne_1>in".rt, "blah")) - } - it("5.3: toAbsoluteTarget on a submodule's data, in an aggregate, within an instance") { - class Top() extends Module { - val i = Instance(Definition(new InstantiatesHasVec())) - amark(i.i1.x.head, "blah") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i:InstantiatesHasVec/i1:HasVec_1>x[0]".rt, "blah")) - } - it("5.4: toAbsoluteTarget on a submodule's data, in an aggregate, within an instance, ILit") { - class MyBundle extends Bundle { val x = UInt(3.W) } - @instantiable - class HasVec() extends Module { - @public val x = Wire(Vec(3, new MyBundle())) - } - @instantiable - class InstantiatesHasVec() extends Module { - @public val i0 = Instance(Definition(new HasVec())) - @public val i1 = Module(new HasVec()) - } - class Top() extends Module { - val i = Instance(Definition(new InstantiatesHasVec())) - amark(i.i1.x.head.x, "blah") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i:InstantiatesHasVec/i1:HasVec_1>x[0].x".rt, "blah")) - } - it("5.5: toAbsoluteTarget on a subinstance") { - class Top() extends Module { - val i = Instance(Definition(new AddTwo())) - amark(i.i1, "blah") - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|Top/i:AddTwo/i1:AddOne".it, "blah")) - } - it("5.6: should work for absolute targets on definition to have correct circuit name") { - class Top extends Module { - val definition = Definition(new AddOneWithAbsoluteAnnotation) - val i0 = Instance(definition) - } - val (_, annos) = getFirrtlAndAnnos(new Top) - annos should contain(MarkAnnotation("~Top|AddOneWithAbsoluteAnnotation>innerWire".rt, "innerWire")) - } - } - describe("6: @instantiable traits should work as expected") { - class MyBundle extends Bundle { - val in = Input(UInt(8.W)) - val out = Output(UInt(8.W)) - } - @instantiable - trait ModuleIntf extends BaseModule { - @public val io = IO(new MyBundle) - } - @instantiable - class ModuleWithCommonIntf(suffix: String = "") extends Module with ModuleIntf { - override def desiredName: String = super.desiredName + suffix - @public val sum = io.in + 1.U - - io.out := sum - } - class BlackBoxWithCommonIntf extends BlackBox with ModuleIntf - - it("6.0: A Module that implements an @instantiable trait should be instantiable as that trait") { - class Top extends Module { - val i: Instance[ModuleIntf] = Instance(Definition(new ModuleWithCommonIntf)) - mark(i.io.in, "gotcha") - mark(i, "inst") - } - val expected = List( - "~Top|Top/i:ModuleWithCommonIntf>io.in".rt -> "gotcha", - "~Top|Top/i:ModuleWithCommonIntf".it -> "inst" - ) - val (chirrtl, annos) = getFirrtlAndAnnos(new Top) - for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain(e) - } - } - it( - "6.1 An @instantiable Module that implements an @instantiable trait should be able to use extension methods from both" - ) { - class Top extends Module { - val i: Instance[ModuleWithCommonIntf] = Instance(Definition(new ModuleWithCommonIntf)) - mark(i.io.in, "gotcha") - mark(i.sum, "also this") - mark(i, "inst") - } - val expected = List( - "~Top|Top/i:ModuleWithCommonIntf>io.in".rt -> "gotcha", - "~Top|Top/i:ModuleWithCommonIntf>sum".rt -> "also this", - "~Top|Top/i:ModuleWithCommonIntf".it -> "inst" - ) - val (chirrtl, annos) = getFirrtlAndAnnos(new Top) - for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain(e) - } - } - it("6.2 A BlackBox that implements an @instantiable trait should be instantiable as that trait") { - class Top extends Module { - val i: Instance[ModuleIntf] = Module(new BlackBoxWithCommonIntf).toInstance - mark(i.io.in, "gotcha") - mark(i, "module") - } - val expected = List( - "~Top|BlackBoxWithCommonIntf>in".rt -> "gotcha", - "~Top|BlackBoxWithCommonIntf".mt -> "module" - ) - val (chirrtl, annos) = getFirrtlAndAnnos(new Top) - for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain(e) - } - } - it("6.3 It should be possible to have Vectors of @instantiable traits mixing concrete subclasses") { - class Top extends Module { - val proto = Definition(new ModuleWithCommonIntf("X")) - val insts: Seq[Instance[ModuleIntf]] = Vector( - Module(new ModuleWithCommonIntf("Y")).toInstance, - Module(new BlackBoxWithCommonIntf).toInstance, - Instance(proto) - ) - mark(insts(0).io.in, "foo") - mark(insts(1).io.in, "bar") - mark(insts(2).io.in, "fizz") - } - val expected = List( - "~Top|ModuleWithCommonIntfY>io.in".rt -> "foo", - "~Top|BlackBoxWithCommonIntf>in".rt -> "bar", - "~Top|Top/insts_2:ModuleWithCommonIntfX>io.in".rt -> "fizz" - ) - val (chirrtl, annos) = getFirrtlAndAnnos(new Top) - for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain(e) - } - } - } - // TODO don't forget to test this with heterogeneous Views (eg. viewing a tuple of a port and non-port as a single Bundle) - describe("7: @instantiable and @public should compose with DataView") { - import chisel3.experimental.dataview._ - it("7.0: should work on simple Views") { - @instantiable - class MyModule extends RawModule { - val in = IO(Input(UInt(8.W))) - @public val out = IO(Output(UInt(8.W))) - val sum = in + 1.U - out := sum + 1.U - @public val foo = in.viewAs[UInt] - @public val bar = sum.viewAs[UInt] - } - class Top extends RawModule { - val foo = IO(Input(UInt(8.W))) - val bar = IO(Output(UInt(8.W))) - val i = Instance(Definition(new MyModule)) - i.foo := foo - bar := i.out - mark(i.out, "out") - mark(i.foo, "foo") - mark(i.bar, "bar") - } - val expectedAnnos = List( - "~Top|Top/i:MyModule>out".rt -> "out", - "~Top|Top/i:MyModule>in".rt -> "foo", - "~Top|Top/i:MyModule>sum".rt -> "bar" - ) - val expectedLines = List( - "i.in <= foo", - "bar <= i.out" - ) - val (chirrtl, annos) = getFirrtlAndAnnos(new Top) - val text = chirrtl.serialize - for (line <- expectedLines) { - text should include(line) - } - for (e <- expectedAnnos.map(MarkAnnotation.tupled)) { - annos should contain(e) - } - } - - ignore("7.1: should work on Aggregate Views") { - import chiselTests.experimental.FlatDecoupledDataView._ - type RegDecoupled = DecoupledIO[FizzBuzz] - @instantiable - class MyModule extends RawModule { - private val a = IO(Flipped(new FlatDecoupled)) - private val b = IO(new FlatDecoupled) - @public val enq = a.viewAs[RegDecoupled] - @public val deq = b.viewAs[RegDecoupled] - @public val enq_valid = enq.valid // Also return a subset of the view - deq <> enq - } - class Top extends RawModule { - val foo = IO(Flipped(new RegDecoupled(new FizzBuzz))) - val bar = IO(new 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 - i.deq.ready := bar.ready - bar.valid := i.deq.valid - bar.bits := i.deq.bits - mark(i.enq, "enq") - mark(i.enq.bits, "enq.bits") - mark(i.deq.bits.fizz, "deq.bits.fizz") - mark(i.enq_valid, "enq_valid") - } - val expectedAnnos = List( - "~Top|Top/i:MyModule>a".rt -> "enq", // Not split, checks 1:1 - "~Top|Top/i:MyModule>a.fizz".rt -> "enq.bits", // Split, checks non-1:1 inner Aggregate - "~Top|Top/i:MyModule>a.buzz".rt -> "enq.bits", - "~Top|Top/i:MyModule>b.fizz".rt -> "deq.bits.fizz", // Checks 1 inner Element - "~Top|Top/i:MyModule>a.valid".rt -> "enq_valid" - ) - val expectedLines = List( - "i.a.valid <= foo.valid", - "foo.ready <= i.a.ready", - "i.a.fizz <= foo.bits.fizz", - "i.a.buzz <= foo.bits.buzz", - "bar.valid <= i.b.valid", - "i.b.ready <= bar.ready", - "bar.bits.fizz <= i.b.fizz", - "bar.bits.buzz <= i.b.buzz" - ) - val (chirrtl, annos) = getFirrtlAndAnnos(new Top) - val text = chirrtl.serialize - for (line <- expectedLines) { - text should include(line) - } - for (e <- expectedAnnos.map(MarkAnnotation.tupled)) { - annos should contain(e) - } - } - - it("7.2: should work on views of views") { - import chiselTests.experimental.SimpleBundleDataView._ - @instantiable - class MyModule extends RawModule { - private val a = IO(Input(UInt(8.W))) - private val b = IO(Output(new BundleA(8))) - @public val in = a.viewAs[UInt].viewAs[UInt] - @public val out = b.viewAs[BundleB].viewAs[BundleA].viewAs[BundleB] - out.bar := in - } - class Top extends RawModule { - val foo = IO(Input(UInt(8.W))) - val bar = IO(Output(new BundleB(8))) - val i = Instance(Definition(new MyModule)) - i.in := foo - bar := i.out - bar.bar := i.out.bar - mark(i.in, "in") - mark(i.out.bar, "out_bar") - } - val expected = List( - "~Top|Top/i:MyModule>a".rt -> "in", - "~Top|Top/i:MyModule>b.foo".rt -> "out_bar" - ) - val lines = List( - "i.a <= foo", - "bar.bar <= i.b.foo" - ) - val (chirrtl, annos) = getFirrtlAndAnnos(new Top) - val text = chirrtl.serialize - for (line <- lines) { - text should include(line) - } - for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain(e) - } - } - - it("7.3: should work with DataView + implicit conversion") { - import chisel3.experimental.conversions._ - @instantiable - class MyModule extends RawModule { - private val a = IO(Input(UInt(8.W))) - private val b = IO(Output(UInt(8.W))) - @public val ports = Seq(a, b) - b := a - } - class Top extends RawModule { - val foo = IO(Input(UInt(8.W))) - val bar = IO(Output(UInt(8.W))) - val i = Instance(Definition(new MyModule)) - i.ports <> Seq(foo, bar) - mark(i.ports, "i.ports") - } - val expected = List( - // Not 1:1 so will get split out - "~Top|Top/i:MyModule>a".rt -> "i.ports", - "~Top|Top/i:MyModule>b".rt -> "i.ports" - ) - val lines = List( - "i.a <= foo", - "bar <= i.b" - ) - val (chirrtl, annos) = getFirrtlAndAnnos(new Top) - val text = chirrtl.serialize - for (line <- lines) { - text should include(line) - } - for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain(e) - } - } - - it("7.4: should work on Views of BlackBoxes") { - @instantiable - class MyBlackBox extends BlackBox { - @public val io = IO(new Bundle { - val in = Input(UInt(8.W)) - val out = Output(UInt(8.W)) - }) - @public val innerView = io.viewAs - @public val foo = io.in.viewAs[UInt] - @public val bar = io.out.viewAs[UInt] - } - class Top extends RawModule { - val foo = IO(Input(UInt(8.W))) - val bar = IO(Output(UInt(8.W))) - val i = Instance(Definition(new MyBlackBox)) - val outerView = i.io.viewAs - i.foo := foo - bar := i.bar - mark(i.foo, "i.foo") - mark(i.bar, "i.bar") - mark(i.innerView.in, "i.innerView.in") - mark(outerView.out, "outerView.out") - } - val inst = "~Top|Top/i:MyBlackBox" - val expectedAnnos = List( - s"$inst>in".rt -> "i.foo", - s"$inst>out".rt -> "i.bar", - s"$inst>in".rt -> "i.innerView.in", - s"$inst>out".rt -> "outerView.out" - ) - val expectedLines = List( - "i.in <= foo", - "bar <= i.out" - ) - val (chirrtl, annos) = getFirrtlAndAnnos(new Top) - val text = chirrtl.serialize - for (line <- expectedLines) { - text should include(line) - } - for (e <- expectedAnnos.map(MarkAnnotation.tupled)) { - annos should contain(e) - } - } - - } - - describe("8: @instantiable and @public should compose with CloneModuleAsRecord") { - it("8.0: it should support @public on a CMAR Record in Definitions") { - @instantiable - class HasCMAR extends Module { - @public val in = IO(Input(UInt(8.W))) - @public val out = IO(Output(UInt(8.W))) - @public val m = Module(new AggregatePortModule) - @public val c = experimental.CloneModuleAsRecord(m) - } - class Top extends Module { - val d = Definition(new HasCMAR) - mark(d.c("io"), "c.io") - val bun = d.c("io").asInstanceOf[Record] - mark(bun.elements("out"), "c.io.out") - } - val expected = List( - "~Top|HasCMAR/c:AggregatePortModule>io".rt -> "c.io", - "~Top|HasCMAR/c:AggregatePortModule>io.out".rt -> "c.io.out" - ) - val (_, annos) = getFirrtlAndAnnos(new Top) - for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain(e) - } - } - it("8.1: it should support @public on a CMAR Record in Instances") { - @instantiable - class HasCMAR extends Module { - @public val in = IO(Input(UInt(8.W))) - @public val out = IO(Output(UInt(8.W))) - @public val m = Module(new AggregatePortModule) - @public val c = experimental.CloneModuleAsRecord(m) - } - class Top extends Module { - val i = Instance(Definition(new HasCMAR)) - mark(i.c("io"), "i.c.io") - val bun = i.c("io").asInstanceOf[Record] - mark(bun.elements("out"), "i.c.io.out") - } - val expected = List( - "~Top|Top/i:HasCMAR/c:AggregatePortModule>io".rt -> "i.c.io", - "~Top|Top/i:HasCMAR/c:AggregatePortModule>io.out".rt -> "i.c.io.out" - ) - val (_, annos) = getFirrtlAndAnnos(new Top) - for (e <- expected.map(MarkAnnotation.tupled)) { - annos should contain(e) - } - } - } - describe("9: isA[..]") { - it("9.0: it should work on simple classes") { - class Top extends Module { - val d = Definition(new AddOne) - require(d.isA[AddOne]) - } - getFirrtlAndAnnos(new Top) - } - it("9.1: it should not work on inner classes") { - class InnerClass extends Module - class Top extends Module { - val d = Definition(new InnerClass) - "require(d.isA[Module])" should compile // ensures that the test below is checking something useful - "require(d.isA[InnerClass])" shouldNot compile - } - getFirrtlAndAnnos(new Top) - } - it("9.2: it should work on super classes") { - class InnerClass extends Module - class Top extends Module { - val d = Definition(new InnerClass) - require(d.isA[Module]) - } - getFirrtlAndAnnos(new Top) - } - it("9.2: it should work after casts") { - class Top extends Module { - val d0: Definition[Module] = Definition(new AddOne) - require(d0.isA[AddOne]) - val d1: Definition[Module] = Definition((new AddOne).asInstanceOf[Module]) - require(d1.isA[AddOne]) - val i0: Instance[Module] = Instance(d0) - require(i0.isA[AddOne]) - val i1: Instance[Module] = Instance(d1) - require(i1.isA[AddOne]) - val i2: Instance[Module] = Instance(Definition(new AddOne)) - require(i2.isA[AddOne]) - } - getFirrtlAndAnnos(new Top) - } - it("9.3 it should ignore type parameters (even though it would be nice if it didn't)") { - class Top extends Module { - val d0: Definition[Module] = Definition(new HasTypeParams(Bool())) - require(d0.isA[HasTypeParams[Bool]]) - require(d0.isA[HasTypeParams[_]]) - require(d0.isA[HasTypeParams[UInt]]) - require(!d0.isA[HasBlah]) - } - getFirrtlAndAnnos(new Top) - } - } - describe("10: Select APIs") { - it("10.0: instancesOf") { - val aspect = aop.inspecting.InspectingAspect({ m: AddTwoMixedModules => - val targets = aop.Select.instancesOf[AddOne](m.toDefinition).map { i: Instance[AddOne] => i.toTarget } - targets should be( - Seq( - "~AddTwoMixedModules|AddTwoMixedModules/i0:AddOne".it, - "~AddTwoMixedModules|AddTwoMixedModules/i1:AddOne_1".it - ) - ) - }) - getFirrtlAndAnnos(new AddTwoMixedModules, Seq(aspect)) - } - it("10.1: instancesIn") { - val aspect = aop.inspecting.InspectingAspect({ m: AddTwoMixedModules => - val insts = aop.Select.instancesIn(m.toDefinition) - val abs = insts.map { i: Instance[BaseModule] => i.toAbsoluteTarget } - val rel = insts.map { i: Instance[BaseModule] => i.toTarget } - abs should be( - Seq( - "~AddTwoMixedModules|AddTwoMixedModules/i0:AddOne".it, - "~AddTwoMixedModules|AddTwoMixedModules/i1:AddOne_1".it - ) - ) - rel should be( - Seq( - "~AddTwoMixedModules|AddTwoMixedModules/i0:AddOne".it, - "~AddTwoMixedModules|AddTwoMixedModules/i1:AddOne_1".it - ) - ) - }) - getFirrtlAndAnnos(new AddTwoMixedModules, Seq(aspect)) - } - it("10.2: allInstancesOf") { - val aspect = aop.inspecting.InspectingAspect({ m: AddFour => - val insts = aop.Select.allInstancesOf[AddOne](m.toDefinition) - val abs = insts.map { i: Instance[AddOne] => i.in.toAbsoluteTarget } - val rel = insts.map { i: Instance[AddOne] => i.in.toTarget } - rel should be( - Seq( - "~AddFour|AddFour/i0:AddTwoMixedModules/i0:AddOne>in".rt, - "~AddFour|AddFour/i0:AddTwoMixedModules/i1:AddOne_1>in".rt, - "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>in".rt, - "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_1>in".rt - ) - ) - abs should be( - Seq( - "~AddFour|AddFour/i0:AddTwoMixedModules/i0:AddOne>in".rt, - "~AddFour|AddFour/i0:AddTwoMixedModules/i1:AddOne_1>in".rt, - "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>in".rt, - "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_1>in".rt - ) - ) - }) - getFirrtlAndAnnos(new AddFour, Seq(aspect)) - } - it("10.3: definitionsOf") { - val aspect = aop.inspecting.InspectingAspect({ m: AddTwoMixedModules => - val targets = aop.Select.definitionsOf[AddOne](m.toDefinition).map { i: Definition[AddOne] => i.in.toTarget } - targets should be( - Seq( - "~AddTwoMixedModules|AddOne>in".rt, - "~AddTwoMixedModules|AddOne_1>in".rt - ) - ) - }) - getFirrtlAndAnnos(new AddTwoMixedModules, Seq(aspect)) - } - it("10.4: definitionsIn") { - val aspect = aop.inspecting.InspectingAspect({ m: AddTwoMixedModules => - val targets = aop.Select.definitionsIn(m.toDefinition).map { i: Definition[BaseModule] => i.toTarget } - targets should be( - Seq( - "~AddTwoMixedModules|AddOne".mt, - "~AddTwoMixedModules|AddOne_1".mt - ) - ) - }) - getFirrtlAndAnnos(new AddTwoMixedModules, Seq(aspect)) - } - it("10.5: allDefinitionsOf") { - val aspect = aop.inspecting.InspectingAspect({ m: AddFour => - val targets = aop.Select.allDefinitionsOf[AddOne](m.toDefinition).map { i: Definition[AddOne] => i.in.toTarget } - targets should be( - Seq( - "~AddFour|AddOne>in".rt, - "~AddFour|AddOne_1>in".rt - ) - ) - }) - getFirrtlAndAnnos(new AddFour, Seq(aspect)) - } - it("10.6: Select.collectDeep should fail when combined with hierarchy package") { - val aspect = aop.inspecting.InspectingAspect({ m: AddFour => - aop.Select.collectDeep(m) { case m: AddOne => m.toTarget } - }) - intercept[Exception] { getFirrtlAndAnnos(new AddFour, Seq(aspect)) } - } - it("10.7: Select.getDeep should fail when combined with hierarchy package") { - val aspect = aop.inspecting.InspectingAspect({ m: AddFour => - aop.Select.getDeep(m) { m: BaseModule => Nil } - }) - intercept[Exception] { getFirrtlAndAnnos(new AddFour, Seq(aspect)) } - } - it("10.8: Select.instances should fail when combined with hierarchy package") { - val aspect = aop.inspecting.InspectingAspect({ m: AddFour => - aop.Select.instances(m) - }) - intercept[Exception] { getFirrtlAndAnnos(new AddFour, Seq(aspect)) } - } - it("10.9: allInstancesOf.ios") { - val aspect = aop.inspecting.InspectingAspect({ m: AddFour => - val abs = aop.Select.allInstancesOf[AddOne](m.toDefinition).flatMap { i: Instance[AddOne] => - aop.Select.ios(i).map(_.toAbsoluteTarget) - } - val rel = aop.Select.allInstancesOf[AddOne](m.toDefinition).flatMap { i: Instance[AddOne] => - aop.Select.ios(i).map(_.toTarget) - } - abs should be( - Seq( - "~AddFour|AddFour/i0:AddTwoMixedModules/i0:AddOne>clock".rt, - "~AddFour|AddFour/i0:AddTwoMixedModules/i0:AddOne>reset".rt, - "~AddFour|AddFour/i0:AddTwoMixedModules/i0:AddOne>in".rt, - "~AddFour|AddFour/i0:AddTwoMixedModules/i0:AddOne>out".rt, - "~AddFour|AddFour/i0:AddTwoMixedModules/i1:AddOne_1>clock".rt, - "~AddFour|AddFour/i0:AddTwoMixedModules/i1:AddOne_1>reset".rt, - "~AddFour|AddFour/i0:AddTwoMixedModules/i1:AddOne_1>in".rt, - "~AddFour|AddFour/i0:AddTwoMixedModules/i1:AddOne_1>out".rt, - "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>clock".rt, - "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>reset".rt, - "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>in".rt, - "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>out".rt, - "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_1>clock".rt, - "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_1>reset".rt, - "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_1>in".rt, - "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_1>out".rt - ) - ) - - rel should be( - Seq( - "~AddFour|AddFour/i0:AddTwoMixedModules/i0:AddOne>clock".rt, - "~AddFour|AddFour/i0:AddTwoMixedModules/i0:AddOne>reset".rt, - "~AddFour|AddFour/i0:AddTwoMixedModules/i0:AddOne>in".rt, - "~AddFour|AddFour/i0:AddTwoMixedModules/i0:AddOne>out".rt, - "~AddFour|AddFour/i0:AddTwoMixedModules/i1:AddOne_1>clock".rt, - "~AddFour|AddFour/i0:AddTwoMixedModules/i1:AddOne_1>reset".rt, - "~AddFour|AddFour/i0:AddTwoMixedModules/i1:AddOne_1>in".rt, - "~AddFour|AddFour/i0:AddTwoMixedModules/i1:AddOne_1>out".rt, - "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>clock".rt, - "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>reset".rt, - "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>in".rt, - "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>out".rt, - "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_1>clock".rt, - "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_1>reset".rt, - "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_1>in".rt, - "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_1>out".rt - ) - ) - }) - getFirrtlAndAnnos(new AddFour, Seq(aspect)) - } - it("10.10: allDefinitionsOf.ios") { - val aspect = aop.inspecting.InspectingAspect({ m: AddFour => - val abs = aop.Select.allDefinitionsOf[AddOne](m.toDefinition).flatMap { i: Definition[AddOne] => - aop.Select.ios(i).map(_.toAbsoluteTarget) - } - val rel = aop.Select.allDefinitionsOf[AddOne](m.toDefinition).flatMap { i: Definition[AddOne] => - aop.Select.ios(i).map(_.toTarget) - } - abs should be( - Seq( - "~AddFour|AddOne>clock".rt, - "~AddFour|AddOne>reset".rt, - "~AddFour|AddOne>in".rt, - "~AddFour|AddOne>out".rt, - "~AddFour|AddOne_1>clock".rt, - "~AddFour|AddOne_1>reset".rt, - "~AddFour|AddOne_1>in".rt, - "~AddFour|AddOne_1>out".rt - ) - ) - - rel should be( - Seq( - "~AddFour|AddOne>clock".rt, - "~AddFour|AddOne>reset".rt, - "~AddFour|AddOne>in".rt, - "~AddFour|AddOne>out".rt, - "~AddFour|AddOne_1>clock".rt, - "~AddFour|AddOne_1>reset".rt, - "~AddFour|AddOne_1>in".rt, - "~AddFour|AddOne_1>out".rt - ) - ) - - }) - getFirrtlAndAnnos(new AddFour, Seq(aspect)) - } - it("10.11 Select.instancesIn for typed BaseModules") { - val aspect = aop.inspecting.InspectingAspect({ m: HasMultipleTypeParamsInside => - val targets = aop.Select.instancesIn(m.toDefinition).map { i: Instance[BaseModule] => i.toTarget } - targets should be( - Seq( - "~HasMultipleTypeParamsInside|HasMultipleTypeParamsInside/i00:HasTypeParams".it, - "~HasMultipleTypeParamsInside|HasMultipleTypeParamsInside/i01:HasTypeParams".it, - "~HasMultipleTypeParamsInside|HasMultipleTypeParamsInside/i10:HasTypeParams_1".it, - "~HasMultipleTypeParamsInside|HasMultipleTypeParamsInside/i11:HasTypeParams_1".it - ) - ) - }) - getFirrtlAndAnnos(new HasMultipleTypeParamsInside, Seq(aspect)) - } - it("10.12 Select.instancesOf for typed BaseModules if type is ignored") { - val aspect = aop.inspecting.InspectingAspect({ m: HasMultipleTypeParamsInside => - val targets = - aop.Select.instancesOf[HasTypeParams[_]](m.toDefinition).map { i: Instance[HasTypeParams[_]] => i.toTarget } - targets should be( - Seq( - "~HasMultipleTypeParamsInside|HasMultipleTypeParamsInside/i00:HasTypeParams".it, - "~HasMultipleTypeParamsInside|HasMultipleTypeParamsInside/i01:HasTypeParams".it, - "~HasMultipleTypeParamsInside|HasMultipleTypeParamsInside/i10:HasTypeParams_1".it, - "~HasMultipleTypeParamsInside|HasMultipleTypeParamsInside/i11:HasTypeParams_1".it - ) - ) - }) - getFirrtlAndAnnos(new HasMultipleTypeParamsInside, Seq(aspect)) - } - it( - "10.13 Select.instancesOf for typed BaseModules even type is specified wrongly (should be ignored, even though we wish it weren't)" - ) { - val aspect = aop.inspecting.InspectingAspect({ m: HasMultipleTypeParamsInside => - val targets = aop.Select.instancesOf[HasTypeParams[SInt]](m.toDefinition).map { i: Instance[HasTypeParams[_]] => - i.toTarget - } - targets should be( - Seq( - "~HasMultipleTypeParamsInside|HasMultipleTypeParamsInside/i00:HasTypeParams".it, - "~HasMultipleTypeParamsInside|HasMultipleTypeParamsInside/i01:HasTypeParams".it, - "~HasMultipleTypeParamsInside|HasMultipleTypeParamsInside/i10:HasTypeParams_1".it, - "~HasMultipleTypeParamsInside|HasMultipleTypeParamsInside/i11:HasTypeParams_1".it - ) - ) - }) - getFirrtlAndAnnos(new HasMultipleTypeParamsInside, Seq(aspect)) - } - } -} diff --git a/src/test/scala/chiselTests/experimental/hierarchy/SeparateElaborationSpec.scala b/src/test/scala/chiselTests/experimental/hierarchy/SeparateElaborationSpec.scala deleted file mode 100644 index 25bbc474..00000000 --- a/src/test/scala/chiselTests/experimental/hierarchy/SeparateElaborationSpec.scala +++ /dev/null @@ -1,495 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.experimental.hierarchy - -import chiselTests.ChiselFunSpec -import chisel3._ -import chisel3.stage.{ChiselCircuitAnnotation, ChiselGeneratorAnnotation, ChiselStage, DesignAnnotation} -import chisel3.experimental.hierarchy.{Definition, Instance} -import chisel3.experimental.hierarchy.ImportDefinitionAnnotation -import firrtl.AnnotationSeq -import firrtl.options.TargetDirAnnotation - -import scala.io.Source - -class SeparateElaborationSpec extends ChiselFunSpec with Utils { - import Examples._ - - /** Return a [[DesignAnnotation]] from a list of annotations. */ - private def getDesignAnnotation[T <: RawModule](annos: AnnotationSeq): DesignAnnotation[T] = { - val designAnnos = annos.flatMap { a => - a match { - case a: DesignAnnotation[T] => Some(a) - case _ => None - } - } - require(designAnnos.length == 1, s"Exactly one DesignAnnotation should exist, but found: $designAnnos.") - designAnnos.head - } - - /** Elaborates [[AddOne]] and returns its [[Definition]]. */ - private def getAddOneDefinition(testDir: String): Definition[AddOne] = { - val dutAnnos = (new ChiselStage).run( - Seq( - ChiselGeneratorAnnotation(() => new AddOne), - TargetDirAnnotation(testDir) - ) - ) - - // Grab DUT definition to pass into testbench - getDesignAnnotation(dutAnnos).design.asInstanceOf[AddOne].toDefinition - } - - /** Return [[Definition]]s of all modules in a circuit. */ - private def allModulesToImportedDefs(annos: AnnotationSeq): Seq[ImportDefinitionAnnotation[_]] = { - annos.flatMap { a => - a match { - case a: ChiselCircuitAnnotation => - a.circuit.components.map { c => ImportDefinitionAnnotation(c.id.toDefinition) } - case _ => Seq.empty - } - } - } - - describe("(0): Name conflicts") { - it("(0.a): should not occur between a Module and an Instance of a previously elaborated Definition.") { - val testDir = createTestDirectory(this.getClass.getSimpleName).toString - - val dutDef = getAddOneDefinition(testDir) - - class Testbench(defn: Definition[AddOne]) extends Module { - val mod = Module(new AddOne) - val inst = Instance(defn) - - // Tie inputs to a value so ChiselStage does not complain - mod.in := 0.U - inst.in := 0.U - dontTouch(mod.out) - } - - (new ChiselStage).run( - Seq( - ChiselGeneratorAnnotation(() => new Testbench(dutDef)), - TargetDirAnnotation(testDir), - ImportDefinitionAnnotation(dutDef) - ) - ) - - val tb_rtl = Source.fromFile(s"$testDir/Testbench.v").getLines.mkString - tb_rtl should include("module AddOne_1(") - tb_rtl should include("AddOne_1 mod (") - (tb_rtl should not).include("module AddOne(") - tb_rtl should include("AddOne inst (") - } - - it( - "(0.b): should not occur between an Instance of a Definition and an Instance of a previously elaborated Definition." - ) { - val testDir = createTestDirectory(this.getClass.getSimpleName).toString - - val dutDef = getAddOneDefinition(testDir) - - class Testbench(defn: Definition[AddOne]) extends Module { - val inst0 = Instance(Definition(new AddOne)) - val inst1 = Instance(defn) - - // Tie inputs to a value so ChiselStage does not complain - inst0.in := 0.U - inst1.in := 0.U - dontTouch(inst0.out) - } - - (new ChiselStage).run( - Seq( - ChiselGeneratorAnnotation(() => new Testbench(dutDef)), - TargetDirAnnotation(testDir), - ImportDefinitionAnnotation(dutDef) - ) - ) - - val tb_rtl = Source.fromFile(s"$testDir/Testbench.v").getLines.mkString - tb_rtl should include("module AddOne_1(") - tb_rtl should include("AddOne_1 inst0 (") - (tb_rtl should not).include("module AddOne(") - tb_rtl should include("AddOne inst1 (") - } - } - - describe("(1): Repeat Module definitions") { - it("(1.a): should not occur when elaborating multiple Instances separately from its Definition.") { - val testDir = createTestDirectory(this.getClass.getSimpleName).toString - - val dutDef = getAddOneDefinition(testDir) - - class Testbench(defn: Definition[AddOne]) extends Module { - val inst0 = Instance(defn) - val inst1 = Instance(defn) - - inst0.in := 0.U - inst1.in := 0.U - } - - // If there is a repeat module definition, FIRRTL emission will fail - (new ChiselStage).emitFirrtl( - gen = new Testbench(dutDef), - args = Array("-td", testDir, "--full-stacktrace"), - annotations = Seq(ImportDefinitionAnnotation(dutDef)) - ) - } - } - - describe("(2): Multiple imported Definitions of modules without submodules") { - it( - "(2.a): should work if a list of imported Definitions is passed between Stages." - ) { - val testDir = createTestDirectory(this.getClass.getSimpleName).toString - - val dutAnnos0 = (new ChiselStage).run( - Seq( - ChiselGeneratorAnnotation(() => new AddOneParameterized(4)), - TargetDirAnnotation(s"$testDir/dutDef0") - ) - ) - val dutDef0 = getDesignAnnotation(dutAnnos0).design.asInstanceOf[AddOneParameterized].toDefinition - - val dutAnnos1 = (new ChiselStage).run( - Seq( - ChiselGeneratorAnnotation(() => new AddOneParameterized(8)), - TargetDirAnnotation(s"$testDir/dutDef1"), - // pass in previously elaborated Definitions - ImportDefinitionAnnotation(dutDef0) - ) - ) - val dutDef1 = getDesignAnnotation(dutAnnos1).design.asInstanceOf[AddOneParameterized].toDefinition - - class Testbench(defn0: Definition[AddOneParameterized], defn1: Definition[AddOneParameterized]) extends Module { - val inst0 = Instance(defn0) - val inst1 = Instance(defn1) - - // Tie inputs to a value so ChiselStage does not complain - inst0.in := 0.U - inst1.in := 0.U - } - - (new ChiselStage).run( - Seq( - ChiselGeneratorAnnotation(() => new Testbench(dutDef0, dutDef1)), - TargetDirAnnotation(testDir), - ImportDefinitionAnnotation(dutDef0), - ImportDefinitionAnnotation(dutDef1) - ) - ) - - val dutDef0_rtl = Source.fromFile(s"$testDir/dutDef0/AddOneParameterized.v").getLines.mkString - dutDef0_rtl should include("module AddOneParameterized(") - val dutDef1_rtl = Source.fromFile(s"$testDir/dutDef1/AddOneParameterized_1.v").getLines.mkString - dutDef1_rtl should include("module AddOneParameterized_1(") - - val tb_rtl = Source.fromFile(s"$testDir/Testbench.v").getLines.mkString - tb_rtl should include("AddOneParameterized inst0 (") - tb_rtl should include("AddOneParameterized_1 inst1 (") - (tb_rtl should not).include("module AddOneParameterized(") - (tb_rtl should not).include("module AddOneParameterized_1(") - } - - it( - "(2.b): should throw an exception if information is not passed between Stages." - ) { - val testDir = createTestDirectory(this.getClass.getSimpleName).toString - - val dutAnnos0 = (new ChiselStage).run( - Seq( - ChiselGeneratorAnnotation(() => new AddOneParameterized(4)), - TargetDirAnnotation(s"$testDir/dutDef0") - ) - ) - val dutDef0 = getDesignAnnotation(dutAnnos0).design.asInstanceOf[AddOneParameterized].toDefinition - - val dutAnnos1 = (new ChiselStage).run( - Seq( - ChiselGeneratorAnnotation(() => new AddOneParameterized(8)), - TargetDirAnnotation(s"$testDir/dutDef1") - ) - ) - val dutDef1 = getDesignAnnotation(dutAnnos1).design.asInstanceOf[AddOneParameterized].toDefinition - - class Testbench(defn0: Definition[AddOneParameterized], defn1: Definition[AddOneParameterized]) extends Module { - val inst0 = Instance(defn0) - val inst1 = Instance(defn1) - - // Tie inputs to a value so ChiselStage does not complain - inst0.in := 0.U - inst1.in := 0.U - } - - // Because these elaborations have no knowledge of each other, they create - // modules of the same name - val dutDef0_rtl = Source.fromFile(s"$testDir/dutDef0/AddOneParameterized.v").getLines.mkString - dutDef0_rtl should include("module AddOneParameterized(") - val dutDef1_rtl = Source.fromFile(s"$testDir/dutDef1/AddOneParameterized.v").getLines.mkString - dutDef1_rtl should include("module AddOneParameterized(") - - val errMsg = intercept[ChiselException] { - (new ChiselStage).run( - Seq( - ChiselGeneratorAnnotation(() => new Testbench(dutDef0, dutDef1)), - TargetDirAnnotation(testDir), - ImportDefinitionAnnotation(dutDef0), - ImportDefinitionAnnotation(dutDef1) - ) - ) - } - errMsg.getMessage should include( - "Expected distinct imported Definition names but found duplicates for: AddOneParameterized" - ) - } - } - - describe("(3): Multiple imported Definitions of modules with submodules") { - it( - "(3.a): should work if a list of imported Definitions for all modules is passed between Stages." - ) { - val testDir = createTestDirectory(this.getClass.getSimpleName).toString - - val dutAnnos0 = (new ChiselStage).run( - Seq( - ChiselGeneratorAnnotation(() => new AddTwoMixedModules), - TargetDirAnnotation(s"$testDir/dutDef0") - ) - ) - val dutDef0 = getDesignAnnotation(dutAnnos0).design.asInstanceOf[AddTwoMixedModules].toDefinition - val importDefinitionAnnos0 = allModulesToImportedDefs(dutAnnos0) - - val dutAnnos1 = (new ChiselStage).run( - Seq( - ChiselGeneratorAnnotation(() => new AddTwoMixedModules), - TargetDirAnnotation(s"$testDir/dutDef1") - ) ++ importDefinitionAnnos0 - ) - val dutDef1 = getDesignAnnotation(dutAnnos1).design.asInstanceOf[AddTwoMixedModules].toDefinition - val importDefinitionAnnos1 = allModulesToImportedDefs(dutAnnos1) - - class Testbench(defn0: Definition[AddTwoMixedModules], defn1: Definition[AddTwoMixedModules]) extends Module { - val inst0 = Instance(defn0) - val inst1 = Instance(defn1) - - // Tie inputs to a value so ChiselStage does not complain - inst0.in := 0.U - inst1.in := 0.U - } - - val dutDef0_rtl = Source.fromFile(s"$testDir/dutDef0/AddTwoMixedModules.v").getLines.mkString - dutDef0_rtl should include("module AddOne(") - dutDef0_rtl should include("module AddTwoMixedModules(") - val dutDef1_rtl = Source.fromFile(s"$testDir/dutDef1/AddTwoMixedModules_1.v").getLines.mkString - dutDef1_rtl should include("module AddOne_2(") - dutDef1_rtl should include("module AddTwoMixedModules_1(") - - (new ChiselStage).run( - Seq( - ChiselGeneratorAnnotation(() => new Testbench(dutDef0, dutDef1)), - TargetDirAnnotation(testDir) - ) ++ importDefinitionAnnos0 ++ importDefinitionAnnos1 - ) - - val tb_rtl = Source.fromFile(s"$testDir/Testbench.v").getLines.mkString - tb_rtl should include("AddTwoMixedModules inst0 (") - tb_rtl should include("AddTwoMixedModules_1 inst1 (") - (tb_rtl should not).include("module AddTwoMixedModules(") - (tb_rtl should not).include("module AddTwoMixedModules_1(") - } - } - - it( - "(3.b): should throw an exception if submodules are not passed between Definition elaborations." - ) { - val testDir = createTestDirectory(this.getClass.getSimpleName).toString - - val dutAnnos0 = (new ChiselStage).run( - Seq( - ChiselGeneratorAnnotation(() => new AddTwoMixedModules), - TargetDirAnnotation(s"$testDir/dutDef0") - ) - ) - val dutDef0 = getDesignAnnotation(dutAnnos0).design.asInstanceOf[AddTwoMixedModules].toDefinition - val importDefinitionAnnos0 = allModulesToImportedDefs(dutAnnos0) - - val dutAnnos1 = (new ChiselStage).run( - Seq( - ChiselGeneratorAnnotation(() => new AddTwoMixedModules), - ImportDefinitionAnnotation(dutDef0), - TargetDirAnnotation(s"$testDir/dutDef1") - ) - ) - val dutDef1 = getDesignAnnotation(dutAnnos1).design.asInstanceOf[AddTwoMixedModules].toDefinition - val importDefinitionAnnos1 = allModulesToImportedDefs(dutAnnos1) - - class Testbench(defn0: Definition[AddTwoMixedModules], defn1: Definition[AddTwoMixedModules]) extends Module { - val inst0 = Instance(defn0) - val inst1 = Instance(defn1) - - // Tie inputs to a value so ChiselStage does not complain - inst0.in := 0.U - inst1.in := 0.U - } - - val dutDef0_rtl = Source.fromFile(s"$testDir/dutDef0/AddTwoMixedModules.v").getLines.mkString - dutDef0_rtl should include("module AddOne(") - dutDef0_rtl should include("module AddTwoMixedModules(") - val dutDef1_rtl = Source.fromFile(s"$testDir/dutDef1/AddTwoMixedModules_1.v").getLines.mkString - dutDef1_rtl should include("module AddOne(") - dutDef1_rtl should include("module AddTwoMixedModules_1(") - - val errMsg = intercept[ChiselException] { - (new ChiselStage).run( - Seq( - ChiselGeneratorAnnotation(() => new Testbench(dutDef0, dutDef1)), - TargetDirAnnotation(testDir) - ) ++ importDefinitionAnnos0 ++ importDefinitionAnnos1 - ) - } - errMsg.getMessage should include( - "Expected distinct imported Definition names but found duplicates for: AddOne" - ) - } - - describe("(4): With ExtMod Names") { - it("(4.a): should pick correct ExtMod names when passed") { - val testDir = createTestDirectory(this.getClass.getSimpleName).toString - - val dutDef = getAddOneDefinition(testDir) - - class Testbench(defn: Definition[AddOne]) extends Module { - val mod = Module(new AddOne) - val inst = Instance(defn) - - // Tie inputs to a value so ChiselStage does not complain - mod.in := 0.U - inst.in := 0.U - dontTouch(mod.out) - } - - (new ChiselStage).run( - Seq( - ChiselGeneratorAnnotation(() => new Testbench(dutDef)), - TargetDirAnnotation(testDir), - ImportDefinitionAnnotation(dutDef, Some("CustomPrefix_AddOne_CustomSuffix")) - ) - ) - - val tb_rtl = Source.fromFile(s"$testDir/Testbench.v").getLines.mkString - - tb_rtl should include("module AddOne_1(") - tb_rtl should include("AddOne_1 mod (") - (tb_rtl should not).include("module AddOne(") - tb_rtl should include("CustomPrefix_AddOne_CustomSuffix inst (") - } - } - - it( - "(4.b): should work if a list of imported Definitions is passed between Stages with ExtModName." - ) { - val testDir = createTestDirectory(this.getClass.getSimpleName).toString - - val dutAnnos0 = (new ChiselStage).run( - Seq( - ChiselGeneratorAnnotation(() => new AddOneParameterized(4)), - TargetDirAnnotation(s"$testDir/dutDef0") - ) - ) - val dutDef0 = getDesignAnnotation(dutAnnos0).design.asInstanceOf[AddOneParameterized].toDefinition - - val dutAnnos1 = (new ChiselStage).run( - Seq( - ChiselGeneratorAnnotation(() => new AddOneParameterized(8)), - TargetDirAnnotation(s"$testDir/dutDef1"), - // pass in previously elaborated Definitions - ImportDefinitionAnnotation(dutDef0) - ) - ) - val dutDef1 = getDesignAnnotation(dutAnnos1).design.asInstanceOf[AddOneParameterized].toDefinition - - class Testbench(defn0: Definition[AddOneParameterized], defn1: Definition[AddOneParameterized]) extends Module { - val inst0 = Instance(defn0) - val inst1 = Instance(defn1) - - // Tie inputs to a value so ChiselStage does not complain - inst0.in := 0.U - inst1.in := 0.U - } - - (new ChiselStage).run( - Seq( - ChiselGeneratorAnnotation(() => new Testbench(dutDef0, dutDef1)), - TargetDirAnnotation(testDir), - ImportDefinitionAnnotation(dutDef0, Some("Inst1_Prefix_AddOnePramaterized_Inst1_Suffix")), - ImportDefinitionAnnotation(dutDef1, Some("Inst2_Prefix_AddOnePrameterized_1_Inst2_Suffix")) - ) - ) - - val dutDef0_rtl = Source.fromFile(s"$testDir/dutDef0/AddOneParameterized.v").getLines.mkString - dutDef0_rtl should include("module AddOneParameterized(") - val dutDef1_rtl = Source.fromFile(s"$testDir/dutDef1/AddOneParameterized_1.v").getLines.mkString - dutDef1_rtl should include("module AddOneParameterized_1(") - - val tb_rtl = Source.fromFile(s"$testDir/Testbench.v").getLines.mkString - tb_rtl should include("Inst1_Prefix_AddOnePramaterized_Inst1_Suffix inst0 (") - tb_rtl should include("Inst2_Prefix_AddOnePrameterized_1_Inst2_Suffix inst1 (") - (tb_rtl should not).include("module AddOneParameterized(") - (tb_rtl should not).include("module AddOneParameterized_1(") - } - - it( - "(4.c): should throw an exception if a list of imported Definitions is passed between Stages with same ExtModName." - ) { - val testDir = createTestDirectory(this.getClass.getSimpleName).toString - - val dutAnnos0 = (new ChiselStage).run( - Seq( - ChiselGeneratorAnnotation(() => new AddOneParameterized(4)), - TargetDirAnnotation(s"$testDir/dutDef0") - ) - ) - val importDefinitionAnnos0 = allModulesToImportedDefs(dutAnnos0) - val dutDef0 = getDesignAnnotation(dutAnnos0).design.asInstanceOf[AddOneParameterized].toDefinition - - val dutAnnos1 = (new ChiselStage).run( - Seq( - ChiselGeneratorAnnotation(() => new AddOneParameterized(8)), - TargetDirAnnotation(s"$testDir/dutDef1"), - // pass in previously elaborated Definitions - ImportDefinitionAnnotation(dutDef0) - ) - ) - val importDefinitionAnnos1 = allModulesToImportedDefs(dutAnnos1) - val dutDef1 = getDesignAnnotation(dutAnnos1).design.asInstanceOf[AddOneParameterized].toDefinition - - class Testbench(defn0: Definition[AddOneParameterized], defn1: Definition[AddOneParameterized]) extends Module { - val inst0 = Instance(defn0) - val inst1 = Instance(defn1) - - // Tie inputs to a value so ChiselStage does not complain - inst0.in := 0.U - inst1.in := 0.U - } - - val dutDef0_rtl = Source.fromFile(s"$testDir/dutDef0/AddOneParameterized.v").getLines.mkString - dutDef0_rtl should include("module AddOneParameterized(") - val dutDef1_rtl = Source.fromFile(s"$testDir/dutDef1/AddOneParameterized_1.v").getLines.mkString - dutDef1_rtl should include("module AddOneParameterized_1(") - - val errMsg = intercept[ChiselException] { - (new ChiselStage).run( - Seq( - ChiselGeneratorAnnotation(() => new Testbench(dutDef0, dutDef1)), - TargetDirAnnotation(testDir), - ImportDefinitionAnnotation(dutDef0, Some("Inst1_Prefix_AddOnePrameterized_Inst1_Suffix")), - ImportDefinitionAnnotation(dutDef1, Some("Inst1_Prefix_AddOnePrameterized_Inst1_Suffix")) - ) - ) - } - errMsg.getMessage should include( - "Expected distinct overrideDef names but found duplicates for: Inst1_Prefix_AddOnePrameterized_Inst1_Suffix" - ) - } -} diff --git a/src/test/scala/chiselTests/experimental/hierarchy/Utils.scala b/src/test/scala/chiselTests/experimental/hierarchy/Utils.scala deleted file mode 100644 index a2e51765..00000000 --- a/src/test/scala/chiselTests/experimental/hierarchy/Utils.scala +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.experimental.hierarchy - -import chisel3._ -import _root_.firrtl.annotations._ -import chisel3.stage.{ChiselCircuitAnnotation, CircuitSerializationAnnotation, DesignAnnotation} -import chiselTests.ChiselRunners -import firrtl.stage.FirrtlCircuitAnnotation -import org.scalatest.matchers.should.Matchers - -trait Utils extends ChiselRunners with chiselTests.Utils with Matchers { - import Annotations._ - // TODO promote to standard API (in FIRRTL) and perhaps even implement with a macro - implicit class Str2RefTarget(str: String) { - def rt: ReferenceTarget = Target.deserialize(str).asInstanceOf[ReferenceTarget] - def it: InstanceTarget = Target.deserialize(str).asInstanceOf[InstanceTarget] - def mt: ModuleTarget = Target.deserialize(str).asInstanceOf[ModuleTarget] - def ct: CircuitTarget = Target.deserialize(str).asInstanceOf[CircuitTarget] - } -} diff --git a/src/test/scala/chiselTests/naming/NamePluginSpec.scala b/src/test/scala/chiselTests/naming/NamePluginSpec.scala deleted file mode 100644 index a787bb80..00000000 --- a/src/test/scala/chiselTests/naming/NamePluginSpec.scala +++ /dev/null @@ -1,362 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.naming - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.aop.Select -import chisel3.experimental.{prefix, treedump} -import chiselTests.{ChiselFlatSpec, Utils} - -class NamePluginSpec extends ChiselFlatSpec with Utils { - implicit val minimumScalaVersion: Int = 12 - - "Scala plugin" should "name internally scoped components" in { - class Test extends Module { - { val mywire = Wire(UInt(3.W)) } - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).head.toTarget.ref should be("mywire") - } - } - - "Scala plugin" should "name internally scoped instances" in { - class Inner extends Module {} - class Test extends Module { - { val myinstance = Module(new Inner) } - } - aspectTest(() => new Test) { top: Test => - Select.instances(top).head.instanceName should be("myinstance") - } - } - - "Scala plugin" should "interact with prefixing" in { - class Test extends Module { - def builder() = { - val wire = Wire(UInt(3.W)) - } - prefix("first") { - builder() - } - prefix("second") { - builder() - } - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("first_wire", "second_wire")) - } - } - - "Scala plugin" should "interact with prefixing so last val name wins" in { - class Test extends Module { - def builder() = { - val wire1 = Wire(UInt(3.W)) - val wire2 = Wire(UInt(3.W)) - wire2 - } - { - val x1 = prefix("first") { - builder() - } - } - { - val x2 = prefix("second") { - builder() - } - } - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("x1_first_wire1", "x1", "x2_second_wire1", "x2")) - } - } - - "Scala plugin" should "name verification ops" in { - class Test extends Module { - val foo, bar = IO(Input(UInt(8.W))) - - { - val x1 = chisel3.assert(1.U === 1.U) - val x2 = cover(foo =/= bar) - val x3 = chisel3.assume(foo =/= 123.U) - val x4 = printf("foo = %d\n", foo) - } - } - val chirrtl = ChiselStage.emitChirrtl(new Test) - (chirrtl should include).regex("assert.*: x1") - (chirrtl should include).regex("cover.*: x2") - (chirrtl should include).regex("assume.*: x3") - (chirrtl should include).regex("printf.*: x4") - } - - "Naming on option" should "work" in { - - class Test extends Module { - def builder(): Option[UInt] = { - val a = Wire(UInt(3.W)) - Some(a) - } - - { val blah = builder() } - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("blah")) - } - } - - "Naming on iterables" should "work" in { - - class Test extends Module { - def builder(): Seq[UInt] = { - val a = Wire(UInt(3.W)) - val b = Wire(UInt(3.W)) - Seq(a, b) - } - { - val blah = { - builder() - } - } - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("blah_0", "blah_1")) - } - } - - "Naming on nested iterables" should "work" in { - - class Test extends Module { - def builder(): Seq[Seq[UInt]] = { - val a = Wire(UInt(3.W)) - val b = Wire(UInt(3.W)) - val c = Wire(UInt(3.W)) - val d = Wire(UInt(3.W)) - Seq(Seq(a, b), Seq(c, d)) - } - { - val blah = { - builder() - } - } - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be( - List( - "blah_0_0", - "blah_0_1", - "blah_1_0", - "blah_1_1" - ) - ) - } - } - - "Naming on custom case classes" should "not work" in { - case class Container(a: UInt, b: UInt) - - class Test extends Module { - def builder(): Container = { - val a = Wire(UInt(3.W)) - val b = Wire(UInt(3.W)) - Container(a, b) - } - - { val blah = builder() } - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("a", "b")) - } - } - - "Multiple names on an IO within a module" should "get the first name" in { - class Test extends RawModule { - { - val a = IO(Output(UInt(3.W))) - val b = a - } - } - - aspectTest(() => new Test) { top: Test => - Select.ios(top).map(_.instanceName) should be(List("a")) - } - } - - "Multiple names on a non-IO" should "get the first name" in { - class Test extends Module { - { - val a = Wire(UInt(3.W)) - val b = a - } - } - - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("a")) - } - } - - "Outer Expression, First Statement naming" should "apply to IO" in { - class Test extends RawModule { - { - val widthOpt: Option[Int] = Some(4) - val out = widthOpt.map { w => - val port = IO(Output(UInt(w.W))) - port - } - val foo = out - val bar = out.get - } - } - - aspectTest(() => new Test) { top: Test => - Select.ios(top).map(_.instanceName) should be(List("out")) - } - } - - "Outer Expression, First Statement naming" should "apply to non-IO" in { - class Test extends RawModule { - { - val widthOpt: Option[Int] = Some(4) - val fizz = widthOpt.map { w => - val wire = Wire(UInt(w.W)) - wire - } - val foo = fizz - val bar = fizz.get - } - } - - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("fizz")) - } - } - - "autoSeed" should "NOT override automatic naming for IO" in { - class Test extends RawModule { - { - val a = IO(Output(UInt(3.W))) - a.autoSeed("b") - } - } - - aspectTest(() => new Test) { top: Test => - Select.ios(top).map(_.instanceName) should be(List("a")) - } - } - - "autoSeed" should "override automatic naming for non-IO" in { - class Test extends Module { - { - val a = Wire(UInt(3.W)) - a.autoSeed("b") - } - } - - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("b")) - } - } - - "Unapply assignments" should "still be named" in { - class Test extends Module { - { - val (a, b) = (Wire(UInt(3.W)), Wire(UInt(3.W))) - } - } - - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("a", "b")) - } - } - - "Unapply assignments" should "not override already named things" in { - class Test extends Module { - { - val x = Wire(UInt(3.W)) - val (a, b) = (x, Wire(UInt(3.W))) - } - } - - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("x", "b")) - } - } - - "Case class unapply assignments" should "be named" in { - case class Foo(x: UInt, y: UInt) - class Test extends Module { - { - def func() = Foo(Wire(UInt(3.W)), Wire(UInt(3.W))) - val Foo(a, b) = func() - } - } - - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("a", "b")) - } - } - - "Complex unapply assignments" should "be named" in { - case class Foo(x: UInt, y: UInt) - class Test extends Module { - { - val w = Wire(UInt(3.W)) - def func() = { - val x = Foo(Wire(UInt(3.W)), Wire(UInt(3.W))) - (x, w) :: Nil - } - val ((Foo(a, _), c) :: Nil) = func() - } - } - - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("w", "a", "_WIRE")) - } - } - - "Recursive types" should "not infinitely loop" in { - // When this fails, it causes a StackOverflow when compiling the tests - // Unfortunately, this doesn't seem to work with assertCompiles(...), it probably ignores the - // custom project scalacOptions - def func(x: String) = { - // We only check types of vals, we don't actually want to run this code though - val y = scala.xml.XML.loadFile(x) - y - } - } - - "Nested val declarations" should "all be named" in { - class Test extends Module { - { - val a = { - val b = { - val c = Wire(UInt(3.W)) - Wire(UInt(3.W)) - } - Wire(UInt(3.W)) - } - } - } - - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("a_b_c", "a_b", "a")) - } - } - - behavior.of("Unnamed values (aka \"Temporaries\")") - - they should "be declared by starting the name with '_'" in { - class Test extends Module { - { - val a = { - val b = { - val _c = Wire(UInt(3.W)) - 4.U // literal so there is no name - } - b - } - } - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("_a_b_c")) - } - } -} diff --git a/src/test/scala/chiselTests/naming/PrefixSpec.scala b/src/test/scala/chiselTests/naming/PrefixSpec.scala deleted file mode 100644 index d8cb3348..00000000 --- a/src/test/scala/chiselTests/naming/PrefixSpec.scala +++ /dev/null @@ -1,550 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.naming - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.aop.Select -import chisel3.experimental.{dump, noPrefix, prefix, treedump} -import chiselTests.{ChiselPropSpec, Utils} -import chisel3.experimental.AffectsChiselPrefix - -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 Module { - def builder(): UInt = { - val wire1 = Wire(UInt(3.W)) - val wire2 = Wire(UInt(3.W)) - wire2 - } - - { - val x1 = prefix("first") { - builder() - } - } - { - val x2 = prefix("second") { - builder() - } - } - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("x1_first_wire1", "x1", "x2_second_wire1", "x2")) - } - } - - property("Nested prefixes should work") { - class Test extends Module { - def builder2(): UInt = { - val wire1 = Wire(UInt(3.W)) - val wire2 = Wire(UInt(3.W)) - wire2 - } - def builder(): UInt = { - val wire1 = Wire(UInt(3.W)) - val wire2 = Wire(UInt(3.W)) - prefix("foo") { - builder2() - } - } - { val x1 = builder() } - { val x2 = builder() } - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be( - List( - "x1_wire1", - "x1_wire2", - "x1_foo_wire1", - "x1", - "x2_wire1", - "x2_wire2", - "x2_foo_wire1", - "x2" - ) - ) - } - } - - property("Prefixing seeded with signal") { - class Test extends Module { - def builder(): UInt = { - val wire = Wire(UInt(3.W)) - wire := 3.U - wire - } - { - val x1 = Wire(UInt(3.W)) - x1 := { - builder() - } - val x2 = Wire(UInt(3.W)) - x2 := { - builder() - } - } - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("x1", "x1_wire", "x2", "x2_wire")) - } - } - - property("Automatic prefixing should work") { - - class Test extends Module { - def builder(): UInt = { - val a = Wire(UInt(3.W)) - val b = Wire(UInt(3.W)) - b - } - - { - val ADAM = builder() - val JACOB = builder() - } - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("ADAM_a", "ADAM", "JACOB_a", "JACOB")) - } - } - - property("No prefixing annotation on defs should work") { - - class Test extends Module { - def builder(): UInt = noPrefix { - val a = Wire(UInt(3.W)) - val b = Wire(UInt(3.W)) - b - } - - { val noprefix = builder() } - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("a", "noprefix")) - } - } - - property("Prefixing on temps should work") { - - class Test extends Module { - def builder(): UInt = { - val a = Wire(UInt(3.W)) - val b = Wire(UInt(3.W)) - a +& (b * a) - } - - { val blah = builder() } - } - aspectTest(() => new Test) { top: Test => - Select.ops(top).map(x => (x._1, x._2.instanceName)) should be( - List( - ("mul", "_blah_T"), - ("add", "blah") - ) - ) - } - } - - property("Prefixing should not leak into child modules") { - class Child extends Module { - { - val wire = Wire(UInt()) - } - } - - class Test extends Module { - { - val child = prefix("InTest") { - Module(new Child) - } - } - } - aspectTest(() => new Test) { top: Test => - Select.wires(Select.instances(top).head).map(_.instanceName) should be(List("wire")) - } - } - - property("Prefixing should not leak into child modules, example 2") { - class Child extends Module { - { - val wire = Wire(UInt()) - } - } - - class Test extends Module { - val x = IO(Input(UInt(3.W))) - val y = { - lazy val module = new Child - val child = Module(module) - } - } - aspectTest(() => new Test) { top: Test => - Select.wires(Select.instances(top).head).map(_.instanceName) should be(List("wire")) - } - } - - property("Instance names should not be added to prefix") { - class Child(tpe: UInt) extends Module { - { - val io = IO(Input(tpe)) - } - } - - class Test extends Module { - { - lazy val module = { - val x = UInt(3.W) - new Child(x) - } - val child = Module(module) - } - } - aspectTest(() => new Test) { top: Test => - Select.ios(Select.instances(top).head).map(_.instanceName) should be(List("clock", "reset", "io")) - } - } - - property("Prefixing should not be caused by nested Iterable[Iterable[Any]]") { - class Test extends Module { - { - val iia = { - val wire = Wire(UInt(3.W)) - List(List("Blah")) - } - } - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("wire")) - } - } - - property("Prefixing should be caused by nested Iterable[Iterable[Data]]") { - class Test extends Module { - { - val iia = { - val wire = Wire(UInt(3.W)) - List(List(3.U)) - } - } - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("iia_wire")) - } - } - - property("Prefixing should NOT be influenced by suggestName") { - class Test extends Module { - { - val wire = { - val x = Wire(UInt(3.W)) // wire_x - Wire(UInt(3.W)).suggestName("foo") - } - } - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("wire_x", "foo")) - } - } - - property("Prefixing should be influenced by the \"current name\" of the signal") { - class Test extends Module { - { - val wire = { - val y = Wire(UInt(3.W)).suggestName("foo") - val x = Wire(UInt(3.W)) // wire_x - y - } - - val wire2 = Wire(UInt(3.W)) - wire2 := { - val x = Wire(UInt(3.W)) // wire2_x - x + 1.U - } - wire2.suggestName("bar") - - val wire3 = Wire(UInt(3.W)) - wire3.suggestName("fizz") - wire3 := { - val x = Wire(UInt(3.W)) // fizz_x - x + 1.U - } - } - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("foo", "wire_x", "bar", "wire2_x", "fizz", "fizz_x")) - } - } - - property("Prefixing have intuitive behavior") { - class Test extends Module { - { - val wire = { - val x = Wire(UInt(3.W)).suggestName("mywire") - val y = Wire(UInt(3.W)).suggestName("mywire2") - y := x - y - } - } - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("wire_mywire", "mywire2")) - } - } - - property("Prefixing on connection to subfields work") { - class Test extends Module { - { - val wire = Wire(new Bundle { - val x = UInt(3.W) - val y = UInt(3.W) - val vec = Vec(4, UInt(3.W)) - }) - wire.x := RegNext(3.U) - wire.y := RegNext(3.U) - wire.vec(0) := RegNext(3.U) - wire.vec(wire.x) := RegNext(3.U) - wire.vec(1.U) := RegNext(3.U) - } - } - aspectTest(() => new Test) { top: Test => - Select.registers(top).map(_.instanceName) should be( - List( - "wire_x_REG", - "wire_y_REG", - "wire_vec_0_REG", - "wire_vec_REG", - "wire_vec_1_REG" - ) - ) - } - } - - property("Prefixing on connection to IOs should work") { - class Child extends Module { - val in = IO(Input(UInt(3.W))) - val out = IO(Output(UInt(3.W))) - out := RegNext(in) - } - class Test extends Module { - { - val child = Module(new Child) - child.in := RegNext(3.U) - } - } - aspectTest(() => new Test) { top: Test => - Select.registers(top).map(_.instanceName) should be( - List( - "child_in_REG" - ) - ) - Select.registers(Select.instances(top).head).map(_.instanceName) should be( - List( - "out_REG" - ) - ) - } - } - - property("Prefixing on bulk connects should work") { - class Child extends Module { - val in = IO(Input(UInt(3.W))) - val out = IO(Output(UInt(3.W))) - out := RegNext(in) - } - class Test extends Module { - { - val child = Module(new Child) - child.in <> RegNext(3.U) - } - } - aspectTest(() => new Test) { top: Test => - Select.registers(top).map(_.instanceName) should be( - List( - "child_in_REG" - ) - ) - Select.registers(Select.instances(top).head).map(_.instanceName) should be( - List( - "out_REG" - ) - ) - } - } - - property("Connections should use the non-prefixed name of the connected Data") { - class Test extends Module { - prefix("foo") { - val x = Wire(UInt(8.W)) - x := { - val w = Wire(UInt(8.W)) - w := 3.U - w + 1.U - } - } - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("foo_x", "foo_x_w")) - } - } - - property("Connections to aggregate fields should use the non-prefixed aggregate name") { - class Test extends Module { - prefix("foo") { - val x = Wire(new Bundle { val bar = UInt(8.W) }) - x.bar := { - val w = Wire(new Bundle { val fizz = UInt(8.W) }) - w.fizz := 3.U - w.fizz + 1.U - } - } - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("foo_x", "foo_x_bar_w")) - } - } - - property("Prefixing with wires in recursive functions should grow linearly") { - class Test extends Module { - def func(bools: Seq[Bool]): Bool = { - if (bools.isEmpty) true.B - else { - val w = Wire(Bool()) - w := bools.head && func(bools.tail) - w - } - } - val in = IO(Input(Vec(4, Bool()))) - val x = func(in) - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("x", "x_w_w", "x_w_w_w", "x_w_w_w_w")) - } - } - - property("Prefixing should work for verification ops") { - class Test extends Module { - val foo, bar = IO(Input(UInt(8.W))) - - { - val x5 = { - val x1 = chisel3.assert(1.U === 1.U) - val x2 = cover(foo =/= bar) - val x3 = chisel3.assume(foo =/= 123.U) - val x4 = printf("foo = %d\n", foo) - x1 - } - } - } - val chirrtl = ChiselStage.emitChirrtl(new Test) - (chirrtl should include).regex("assert.*: x5") - (chirrtl should include).regex("cover.*: x5_x2") - (chirrtl should include).regex("assume.*: x5_x3") - (chirrtl should include).regex("printf.*: x5_x4") - } - - property("Leading '_' in val names should be ignored in prefixes") { - class Test extends Module { - { - val a = { - val _b = { - val c = Wire(UInt(3.W)) - 4.U // literal because there is no name - } - _b - } - } - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("a_b_c")) - } - } - - // This checks that we don't just blanket ignore leading _ in prefixes - property("User-specified prefixes with '_' should be respected") { - class Test extends Module { - { - val a = { - val _b = prefix("_b") { - val c = Wire(UInt(3.W)) - } - 4.U - } - } - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("a__b_c")) - } - } - - property("Leading '_' in signal names should be ignored in prefixes from connections") { - class Test extends Module { - { - val a = { - val b = { - val _c = IO(Output(UInt(3.W))) // port so not selected as wire - _c := { - val d = Wire(UInt(3.W)) - d - } - 4.U // literal so there is no name - } - b - } - } - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("a_b_c_d")) - } - } - - property("Prefixing of AffectsChiselPrefix objects should work") { - class NotAData extends AffectsChiselPrefix { - val value = Wire(UInt(3.W)) - } - class NotADataUnprefixed { - val value = Wire(UInt(3.W)) - } - class Test extends Module { - { - val nonData = new NotAData - // Instance name of nonData.value should be nonData_value - nonData.value := RegNext(3.U) - - val nonData2 = new NotADataUnprefixed - // Instance name of nonData2.value should be value - nonData2.value := RegNext(3.U) - } - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("nonData_value", "value")) - } - } - property("Prefixing should not be affected by repeated calls of suggestName") { - class Test extends Module { - val in = IO(Input(UInt(3.W))) - val prefixed = { - val wire = Wire(UInt(3.W)).suggestName("wire") // "prefixed_wire" - wire := in - - val thisShouldNotBeHere = { - // Second suggestName doesn't modify the instanceName since it was - // already suggested, but also should not modify the prefix either - - // Incorrect behavior would rename the wire to - // "prefixed_thisShouldNotBeHere_wire" - wire.suggestName("wire") - - val out = IO(Output(UInt(3.W))) - out := wire - out - } - thisShouldNotBeHere - } - } - aspectTest(() => new Test) { top: Test => - Select.wires(top).map(_.instanceName) should be(List("prefixed_wire")) - } - } -} diff --git a/src/test/scala/chiselTests/naming/ReflectiveNamingSpec.scala b/src/test/scala/chiselTests/naming/ReflectiveNamingSpec.scala deleted file mode 100644 index baa991dd..00000000 --- a/src/test/scala/chiselTests/naming/ReflectiveNamingSpec.scala +++ /dev/null @@ -1,161 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.naming - -import chisel3._ -import chiselTests.{ChiselFlatSpec, Utils} - -class ReflectiveNamingSpec extends ChiselFlatSpec with Utils { - - behavior.of("Reflective naming") - - private def emitChirrtl(gen: => RawModule): String = { - // Annoyingly need to emit files to use CLI - val targetDir = createTestDirectory(this.getClass.getSimpleName).toString - val args = Array("--warn:reflective-naming", "-td", targetDir) - (new chisel3.stage.ChiselStage).emitChirrtl(gen, args) - } - - it should "NOT warn when no names are changed" in { - class Example extends Module { - val foo, bar = IO(Input(UInt(8.W))) - val out = IO(Output(UInt(8.W))) - - val sum = foo +& bar - out := sum - } - val (log, chirrtl) = grabLog(emitChirrtl(new Example)) - log should equal("") - chirrtl should include("node sum = add(foo, bar)") - } - - it should "warn when changing the name of a node" in { - class Example extends Module { - val foo, bar = IO(Input(UInt(8.W))) - val out = IO(Output(UInt(8.W))) - - val sum = foo +& bar - val fuzz = sum - out := sum - } - val (log, chirrtl) = grabLog(emitChirrtl(new Example)) - log should include("'sum' is renamed by reflection to 'fuzz'") - chirrtl should include("node fuzz = add(foo, bar)") - } - - // This also checks correct prefix reversing - it should "warn when changing the name of a node with a prefix in the name" in { - class Example extends Module { - val foo, bar = IO(Input(UInt(8.W))) - val out = IO(Output(UInt(8.W))) - - // This is sketch, don't do this - var fuzz = 0.U - out := { - val sum = { - val node = foo +& bar - fuzz = node - node +% 0.U - } - sum - } - } - val (log, chirrtl) = grabLog(emitChirrtl(new Example)) - log should include("'out_sum_node' is renamed by reflection to 'fuzz'") - chirrtl should include("node fuzz = add(foo, bar)") - } - - it should "warn when changing the name of a Module instance" in { - import chisel3.util._ - class Example extends Module { - val enq = IO(Flipped(Decoupled(UInt(8.W)))) - val deq = IO(Decoupled(UInt(8.W))) - - val q = Module(new Queue(UInt(8.W), 4)) - q.io.enq <> enq - deq <> q.io.deq - - val fuzz = q - } - val (log, chirrtl) = grabLog(emitChirrtl(new Example)) - log should include("'q' is renamed by reflection to 'fuzz'") - chirrtl should include("inst fuzz of Queue") - } - - it should "warn when changing the name of an Instance" in { - import chisel3.experimental.hierarchy.{Definition, Instance} - import chiselTests.experimental.hierarchy.Examples.AddOne - class Example extends Module { - val defn = Definition(new AddOne) - val inst = Instance(defn) - val fuzz = inst - } - val (log, chirrtl) = grabLog(emitChirrtl(new Example)) - log should include("'inst' is renamed by reflection to 'fuzz'") - chirrtl should include("inst fuzz of AddOne") - } - - it should "warn when changing the name of a Mem" in { - class Example extends Module { - val mem = SyncReadMem(8, UInt(8.W)) - - val fuzz = mem - } - val (log, chirrtl) = grabLog(emitChirrtl(new Example)) - log should include("'mem' is renamed by reflection to 'fuzz'") - chirrtl should include("smem fuzz") - } - - it should "NOT warn when changing the name of a verification statement" in { - class Example extends Module { - val in = IO(Input(UInt(8.W))) - val z = chisel3.assert(in =/= 123.U) - val fuzz = z - } - val (log, chirrtl) = grabLog(emitChirrtl(new Example)) - log should equal("") - // But the name is actually changed - (chirrtl should include).regex("assert.*: fuzz") - } - - it should "NOT warn when \"naming\" a literal" in { - class Example extends Module { - val out = IO(Output(UInt(8.W))) - - val sum = 0.U - val fuzz = sum - out := sum - } - val (log, chirrtl) = grabLog(emitChirrtl(new Example)) - log should equal("") - chirrtl should include("out <= UInt") - } - - it should "NOT warn when \"naming\" a field of an Aggregate" in { - class Example extends Module { - val io = IO(new Bundle { - val in = Input(UInt(8.W)) - val out = Output(UInt(8.W)) - }) - val in = io.in - val out = io.out - out := in - } - val (log, chirrtl) = grabLog(emitChirrtl(new Example)) - log should equal("") - chirrtl should include("io.out <= io.in") - } - - it should "NOT warn when \"naming\" unbound Data" in { - class Example extends Module { - val in = IO(Input(UInt(8.W))) - val out = IO(Output(UInt(8.W))) - val z = UInt(8.W) - val a = z - out := in - } - val (log, chirrtl) = grabLog(emitChirrtl(new Example)) - log should equal("") - chirrtl should include("out <= in") - } -} diff --git a/src/test/scala/chiselTests/stage/ChiselAnnotationsSpec.scala b/src/test/scala/chiselTests/stage/ChiselAnnotationsSpec.scala deleted file mode 100644 index 9dac820c..00000000 --- a/src/test/scala/chiselTests/stage/ChiselAnnotationsSpec.scala +++ /dev/null @@ -1,67 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.stage - -import chisel3._ -import chisel3.stage.{ChiselCircuitAnnotation, ChiselGeneratorAnnotation, DesignAnnotation} -import firrtl.options.OptionsException -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers - -class ChiselAnnotationsSpecFoo extends RawModule { - val in = IO(Input(Bool())) - val out = IO(Output(Bool())) - out := ~in -} - -class ChiselAnnotationsSpecBaz(name: String) extends ChiselAnnotationsSpecFoo { - override val desiredName = name -} - -class ChiselAnnotationsSpecQux extends ChiselAnnotationsSpecFoo { - /* This printf requires an implicit clock and reset, but RawModule has none. This will thereby fail elaboration. */ - printf("hello") -} - -class ChiselAnnotation - -class ChiselAnnotationsSpec extends AnyFlatSpec with Matchers { - - behavior.of("ChiselGeneratorAnnotation elaboration") - - it should "elaborate to a ChiselCircuitAnnotation" in { - val annotation = ChiselGeneratorAnnotation(() => new ChiselAnnotationsSpecFoo) - val res = annotation.elaborate - res(0) shouldBe a[ChiselCircuitAnnotation] - res(1) shouldBe a[DesignAnnotation[ChiselAnnotationsSpecFoo]] - } - - it should "throw an exception if elaboration fails" in { - val annotation = ChiselGeneratorAnnotation(() => new ChiselAnnotationsSpecQux) - intercept[ChiselException] { annotation.elaborate } - } - - behavior.of("ChiselGeneratorAnnotation when stringly constructing from Module names") - - it should "elaborate from a String" in { - val annotation = ChiselGeneratorAnnotation("chiselTests.stage.ChiselAnnotationsSpecFoo") - val res = annotation.elaborate - res(0) shouldBe a[ChiselCircuitAnnotation] - res(1) shouldBe a[DesignAnnotation[ChiselAnnotationsSpecFoo]] - } - - it should "throw an exception if elaboration from a String refers to nonexistant class" in { - val bar = "chiselTests.stage.ChiselAnnotationsSpecBar" - val annotation = ChiselGeneratorAnnotation(bar) - intercept[OptionsException] { annotation.elaborate }.getMessage should startWith(s"Unable to locate module '$bar'") - } - - it should "throw an exception if elaboration from a String refers to an anonymous class" in { - val baz = "chiselTests.stage.ChiselAnnotationsSpecBaz" - val annotation = ChiselGeneratorAnnotation(baz) - intercept[OptionsException] { annotation.elaborate }.getMessage should startWith( - s"Unable to create instance of module '$baz'" - ) - } - -} diff --git a/src/test/scala/chiselTests/stage/ChiselMainSpec.scala b/src/test/scala/chiselTests/stage/ChiselMainSpec.scala deleted file mode 100644 index e8773111..00000000 --- a/src/test/scala/chiselTests/stage/ChiselMainSpec.scala +++ /dev/null @@ -1,325 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.stage - -import chisel3._ -import chisel3.stage.ChiselMain -import java.io.File - -import chisel3.aop.inspecting.{InspectingAspect, InspectorAspect} -import org.scalatest.GivenWhenThen -import org.scalatest.featurespec.AnyFeatureSpec -import org.scalatest.matchers.should.Matchers -import org.scalatest.Inside._ -import org.scalatest.EitherValues._ - -import scala.io.Source -import firrtl.Parser - -object ChiselMainSpec { - - /** A module that connects two different types together resulting in an elaboration error */ - class DifferentTypesModule extends RawModule { - val in = IO(Input(UInt(1.W))) - val out = IO(Output(SInt(1.W))) - out := in - } - - /** A module that connects two of the same types together */ - class SameTypesModule extends Module { - val in = IO(Input(UInt(1.W))) - val out = IO(Output(UInt(1.W))) - out := in - } - - /** A module that fails a requirement */ - class FailingRequirementModule extends RawModule { - require(false, "the user wrote a failing requirement") - } - - /** A module that triggers a Builder.error (as opposed to exception) */ - class BuilderErrorModule extends RawModule { - val w = Wire(UInt(8.W)) - w(3, -1) - } -} - -case class TestClassAspect() - extends InspectorAspect[RawModule]({ _: RawModule => - println("Ran inspectingAspect") - }) - -case object TestObjectAspect - extends InspectorAspect[RawModule]({ _: RawModule => - println("Ran inspectingAspect") - }) - -class ChiselMainSpec extends AnyFeatureSpec with GivenWhenThen with Matchers with chiselTests.Utils { - - import ChiselMainSpec._ - - class ChiselMainFixture { - Given("a Chisel stage") - val stage = ChiselMain - } - - class TargetDirectoryFixture(dirName: String) { - val dir = new File(s"test_run_dir/ChiselStageSpec/$dirName") - val buildDir = new File(dir + "/build") - dir.mkdirs() - } - - case class ChiselMainTest( - args: Array[String], - generator: Option[Class[_ <: RawModule]] = None, - files: Seq[String] = Seq.empty, - stdout: Seq[Either[String, String]] = Seq.empty, - stderr: Seq[Either[String, String]] = Seq.empty, - result: Int = 0, - fileChecks: Map[String, File => Unit] = Map.empty) { - def testName: String = "args" + args.mkString("_") - def argsString: String = args.mkString(" ") - } - - /** A test of ChiselMain that is going to involve catching an exception. - * @param args command line arguments (excluding --module) to pass in - * @param generator the module to build (used to generate --module) - * @param message snippets of text that should appear (Right) or not appear (Left) in the exception message - * @param stdout snippets of text that should appear (Right) or not appear (Left) in STDOUT - * @param stderr snippets of text that should appear (Right) or not appear (Left) in STDERR - * @param stackTrace snippets of text that should appear (Right) or not appear (Left) in the stack trace - * @tparam the type of exception that should occur - */ - case class ChiselMainExceptionTest[A <: Throwable]( - args: Array[String], - generator: Option[Class[_ <: RawModule]] = None, - message: Seq[Either[String, String]] = Seq.empty, - stdout: Seq[Either[String, String]] = Seq.empty, - stderr: Seq[Either[String, String]] = Seq.empty, - stackTrace: Seq[Either[String, String]] = Seq.empty) { - def testName: String = "args" + args.mkString("_") - def argsString: String = args.mkString(" ") - } - - def runStageExpectFiles(p: ChiselMainTest): Unit = { - Scenario(s"""User runs Chisel Stage with '${p.argsString}'""") { - val f = new ChiselMainFixture - val td = new TargetDirectoryFixture(p.testName) - - p.files.foreach(f => new File(td.buildDir + s"/$f").delete()) - - When(s"""the user tries to compile with '${p.argsString}'""") - val module: Array[String] = - (if (p.generator.nonEmpty) { Array("--module", p.generator.get.getName) } - else { Array.empty[String] }) - f.stage.main(Array("-td", td.buildDir.toString) ++ module ++ p.args) - val (stdout, stderr, result) = - grabStdOutErr { - catchStatus { - f.stage.main(Array("-td", td.buildDir.toString) ++ module ++ p.args) - } - } - - p.stdout.foreach { - case Right(a) => - Then(s"""STDOUT should include "$a"""") - stdout should include(a) - case Left(a) => - Then(s"""STDOUT should not include "$a"""") - (stdout should not).include(a) - } - - p.stderr.foreach { - case Right(a) => - Then(s"""STDERR should include "$a"""") - stderr should include(a) - case Left(a) => - Then(s"""STDERR should not include "$a"""") - (stderr should not).include(a) - } - - p.result match { - case 0 => - And(s"the exit code should be 0") - result shouldBe a[Right[_, _]] - case a => - And(s"the exit code should be $a") - result shouldBe (Left(a)) - } - - p.files.foreach { f => - And(s"file '$f' should be emitted in the target directory") - val out = new File(td.buildDir + s"/$f") - out should (exist) - p.fileChecks.get(f).map(_(out)) - } - } - } - - /** Run a ChiselMainExceptionTest and verify that all the properties it spells out hold. - * @param p the test to run - * @tparam the type of the exception to catch (you shouldn't have to explicitly provide this) - */ - def runStageExpectException[A <: Throwable: scala.reflect.ClassTag](p: ChiselMainExceptionTest[A]): Unit = { - Scenario(s"""User runs Chisel Stage with '${p.argsString}'""") { - val f = new ChiselMainFixture - val td = new TargetDirectoryFixture(p.testName) - - When(s"""the user tries to compile with '${p.argsString}'""") - val module: Array[String] = - (if (p.generator.nonEmpty) { Array("--module", p.generator.get.getName) } - else { Array.empty[String] }) - val (stdout, stderr, result) = - grabStdOutErr { - catchStatus { - intercept[A] { - f.stage.main(Array("-td", td.buildDir.toString) ++ module ++ p.args) - } - } - } - - Then("the expected exception was thrown") - (result should be).a('right) - val exception = result.right.get - info(s""" - Exception was a "${exception.getClass.getName}"""") - - val message = exception.getMessage - p.message.foreach { - case Right(a) => - Then(s"""STDOUT should include "$a"""") - message should include(a) - case Left(a) => - Then(s"""STDOUT should not include "$a"""") - (message should not).include(a) - } - - p.stdout.foreach { - case Right(a) => - Then(s"""STDOUT should include "$a"""") - stdout should include(a) - case Left(a) => - Then(s"""STDOUT should not include "$a"""") - (stdout should not).include(a) - } - - p.stderr.foreach { - case Right(a) => - Then(s"""STDERR should include "$a"""") - stderr should include(a) - case Left(a) => - Then(s"""STDERR should not include "$a"""") - (stderr should not).include(a) - } - - val stackTraceString = exception.getStackTrace.mkString("\n") - p.stackTrace.foreach { - case Left(a) => - And(s"""the stack does not include "$a"""") - (stackTraceString should not).include(a) - case Right(a) => - And(s"""the stack trace includes "$a"""") - stackTraceString should include(a) - } - - } - } - - info("As a Chisel user") - info("I compile a design") - Feature("show elaborating message") { - runStageExpectFiles( - ChiselMainTest(args = Array("-X", "high"), generator = Some(classOf[SameTypesModule])) - ) - } - - info("I screw up and compile some bad code") - Feature("Stack trace trimming of ChiselException") { - Seq( - ChiselMainExceptionTest[chisel3.internal.ChiselException]( - args = Array("-X", "low"), - generator = Some(classOf[DifferentTypesModule]), - stackTrace = Seq(Left("java"), Right(classOf[DifferentTypesModule].getName)) - ), - ChiselMainExceptionTest[chisel3.internal.ChiselException]( - args = Array("-X", "low", "--full-stacktrace"), - generator = Some(classOf[DifferentTypesModule]), - stackTrace = Seq(Right("java"), Right(classOf[DifferentTypesModule].getName)) - ) - ).foreach(runStageExpectException) - } - Feature("Stack trace trimming of user exceptions") { - Seq( - ChiselMainExceptionTest[java.lang.IllegalArgumentException]( - args = Array("-X", "low"), - generator = Some(classOf[FailingRequirementModule]), - stackTrace = Seq(Right(classOf[FailingRequirementModule].getName), Left("java")) - ), - ChiselMainExceptionTest[java.lang.IllegalArgumentException]( - args = Array("-X", "low", "--full-stacktrace"), - generator = Some(classOf[FailingRequirementModule]), - stackTrace = Seq(Right(classOf[FailingRequirementModule].getName), Right("java")) - ) - ).foreach(runStageExpectException) - } - Feature("Stack trace trimming and Builder.error errors") { - Seq( - ChiselMainExceptionTest[chisel3.internal.ChiselException]( - args = Array("-X", "low"), - generator = Some(classOf[BuilderErrorModule]), - message = Seq(Right("Fatal errors during hardware elaboration")), - stdout = Seq( - Right( - "ChiselMainSpec.scala:43: Invalid bit range (3,-1) in class chiselTests.stage.ChiselMainSpec$BuilderErrorModule" - ) - ) - ) - ).foreach(runStageExpectException) - } - - Feature("Specifying a custom output file") { - runStageExpectFiles( - ChiselMainTest( - args = Array("--chisel-output-file", "Foo", "--no-run-firrtl"), - generator = Some(classOf[SameTypesModule]), - files = Seq("Foo.fir"), - fileChecks = Map( - "Foo.fir" -> { file => - And("It should be valid FIRRTL") - Parser.parse(Source.fromFile(file).mkString) - } - ) - ) - ) - runStageExpectFiles( - ChiselMainTest( - args = Array("--chisel-output-file", "Foo.pb", "--no-run-firrtl"), - generator = Some(classOf[SameTypesModule]), - files = Seq("Foo.pb"), - fileChecks = Map( - "Foo.pb" -> { file => - And("It should be valid ProtoBuf") - firrtl.proto.FromProto.fromFile(file.toString) - } - ) - ) - ) - } - - info("As an aspect writer") - info("I write an aspect") - Feature("Running aspects via the command line") { - Seq( - ChiselMainTest( - args = Array("-X", "high", "--with-aspect", "chiselTests.stage.TestClassAspect"), - generator = Some(classOf[SameTypesModule]), - stdout = Seq(Right("Ran inspectingAspect")) - ), - ChiselMainTest( - args = Array("-X", "high", "--with-aspect", "chiselTests.stage.TestObjectAspect"), - generator = Some(classOf[SameTypesModule]), - stdout = Seq(Right("Ran inspectingAspect")) - ) - ).foreach(runStageExpectFiles) - } - -} diff --git a/src/test/scala/chiselTests/stage/ChiselOptionsViewSpec.scala b/src/test/scala/chiselTests/stage/ChiselOptionsViewSpec.scala deleted file mode 100644 index b164ff20..00000000 --- a/src/test/scala/chiselTests/stage/ChiselOptionsViewSpec.scala +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.stage - -import firrtl.options.Viewer.view -import firrtl.RenameMap - -import chisel3.stage._ -import chisel3.internal.firrtl.Circuit -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers - -class ChiselOptionsViewSpec extends AnyFlatSpec with Matchers { - - behavior.of(ChiselOptionsView.getClass.getName) - - it should "construct a view from an AnnotationSeq" in { - val bar = Circuit("bar", Seq.empty, Seq.empty, RenameMap()) - val annotations = Seq( - NoRunFirrtlCompilerAnnotation, - PrintFullStackTraceAnnotation, - ChiselOutputFileAnnotation("foo"), - ChiselCircuitAnnotation(bar) - ) - val out = view[ChiselOptions](annotations) - - info("runFirrtlCompiler was set to false") - out.runFirrtlCompiler should be(false) - - info("printFullStackTrace was set to true") - out.printFullStackTrace should be(true) - - info("outputFile was set to 'foo'") - out.outputFile should be(Some("foo")) - - info("chiselCircuit was set to circuit 'bar'") - out.chiselCircuit should be(Some(bar)) - - } - -} diff --git a/src/test/scala/chiselTests/stage/ChiselStageSpec.scala b/src/test/scala/chiselTests/stage/ChiselStageSpec.scala deleted file mode 100644 index f0f383da..00000000 --- a/src/test/scala/chiselTests/stage/ChiselStageSpec.scala +++ /dev/null @@ -1,293 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.stage - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.testers.TesterDriver.createTestDirectory - -import chiselTests.Utils - -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers - -import firrtl.options.Dependency - -object ChiselStageSpec { - - class Bar extends Module { - val in = IO(Input(UInt(4.W))) - val out = IO(Output(UInt(4.W))) - out := ~in - } - - class Foo extends Module { - val addr = IO(Input(UInt(4.W))) - val out = IO(Output(Bool())) - val memory = SyncReadMem(8, Bool()) - val bar = Module(new Bar) - bar.in := addr - out := memory(bar.out) - } - - class UserExceptionModule extends RawModule { - assert(false, "User threw an exception") - } - - class UserExceptionNoStackTrace extends RawModule { - throw new Exception("Something bad happened") with scala.util.control.NoStackTrace - } - - class RecoverableError extends RawModule { - 3.U >> -1 - } - -} - -class ChiselStageSpec extends AnyFlatSpec with Matchers with Utils { - - import ChiselStageSpec._ - - private trait ChiselStageFixture { - val stage = new ChiselStage - } - - behavior.of("ChiselStage$.emitChirrtl") - - it should "return a CHIRRTL string" in { - ChiselStage.emitChirrtl(new Foo) should include("infer mport") - } - - behavior.of("ChiselStage$.emitFirrtl") - - it should "return a High FIRRTL string" in { - ChiselStage.emitFirrtl(new Foo) should include("mem memory") - } - - it should "return a flattened FIRRTL string with '-e high'" in { - val args = Array("-e", "high", "-td", createTestDirectory(this.getClass.getSimpleName).toString) - (new ChiselStage) - .emitFirrtl(new Foo, args) should include("module Bar") - } - - behavior.of("ChiselStage$.emitVerilog") - - it should "return a Verilog string" in { - ChiselStage.emitVerilog(new Foo) should include("endmodule") - } - - it should "return a flattened Verilog string with '-e verilog'" in { - val args = Array("-e", "verilog", "-td", createTestDirectory(this.getClass.getSimpleName).toString) - (new ChiselStage) - .emitVerilog(new Foo, args) should include("module Bar") - } - - behavior.of("ChiselStage$.elaborate") - - ignore should "generate a Chisel circuit from a Chisel module" in { - info("no files were written") - catchWrites { ChiselStage.elaborate(new Foo) } shouldBe a[Right[_, _]] - } - - behavior.of("ChiselStage$.convert") - - ignore should "generate a CHIRRTL circuit from a Chisel module" in { - info("no files were written") - catchWrites { ChiselStage.convert(new Foo) } shouldBe a[Right[_, _]] - } - - ignore should "generate a FIRRTL circuit from a CHIRRTL circuit" in { - info("no files were written") - catchWrites { - ChiselStage.convert(ChiselStage.elaborate(new Foo)) - } shouldBe a[Right[_, _]] - } - - behavior.of("ChiselStage$.emitChirrtl") - - ignore should "generate a CHIRRTL string from a Chisel module" in { - val wrapped = catchWrites { ChiselStage.emitChirrtl(new Foo) } - - info("no files were written") - wrapped shouldBe a[Right[_, _]] - - info("returned string looks like FIRRTL") - wrapped.right.get should include("circuit") - } - - behavior.of("ChiselStage$.emitFirrtl") - - ignore should "generate a FIRRTL string from a Chisel module" in { - val wrapped = catchWrites { ChiselStage.emitFirrtl(new Foo) } - - info("no files were written") - wrapped shouldBe a[Right[_, _]] - - info("returned string looks like FIRRTL") - wrapped.right.get should include("circuit") - } - - behavior.of("ChiselStage$.emitVerilog") - - ignore should "generate a Verilog string from a Chisel module" in { - val wrapped = catchWrites { ChiselStage.emitVerilog(new Foo) } - - info("no files were written") - wrapped shouldBe a[Right[_, _]] - - info("returned string looks like Verilog") - wrapped.right.get should include("endmodule") - } - - behavior.of("ChiselStage$.emitSystemVerilog") - - ignore should "generate a SystemvVerilog string from a Chisel module" in { - val wrapped = catchWrites { ChiselStage.emitSystemVerilog(new Foo) } - info("no files were written") - wrapped shouldBe a[Right[_, _]] - - info("returned string looks like Verilog") - wrapped.right.get should include("endmodule") - } - - behavior.of("ChiselStage phase ordering") - - it should "only run elaboration once" in new ChiselStageFixture { - info("Phase order is:\n" + stage.phaseManager.prettyPrint(" ")) - - val order = stage.phaseManager.flattenedTransformOrder.map(Dependency.fromTransform) - - info("Elaborate only runs once") - exactly(1, order) should be(Dependency[chisel3.stage.phases.Elaborate]) - } - - behavior.of("ChiselStage$ exception handling") - - it should "truncate a user exception" in { - info("The user's java.lang.AssertionError was thrown") - val exception = intercept[java.lang.AssertionError] { - ChiselStage.emitChirrtl(new UserExceptionModule) - } - - val message = exception.getMessage - info("The exception includes the user's message") - message should include("User threw an exception") - - info("The stack trace is trimmed") - (exception.getStackTrace.mkString("\n") should not).include("java") - } - - it should "NOT add a stack trace to an exception with no stack trace" in { - val exception = intercept[java.lang.Exception] { - ChiselStage.emitChirrtl(new UserExceptionNoStackTrace) - } - - val message = exception.getMessage - info("The exception includes the user's message") - message should include("Something bad happened") - - info("The exception should not contain a stack trace") - exception.getStackTrace should be(Array()) - } - - it should "NOT include a stack trace for recoverable errors" in { - val exception = intercept[java.lang.Exception] { - ChiselStage.emitChirrtl(new RecoverableError) - } - - val message = exception.getMessage - info("The exception includes the standard error message") - message should include("Fatal errors during hardware elaboration. Look above for error list.") - - info("The exception should not contain a stack trace") - exception.getStackTrace should be(Array()) - } - - behavior.of("ChiselStage exception handling") - - it should "truncate a user exception" in { - info("The user's java.lang.AssertionError was thrown") - val exception = intercept[java.lang.AssertionError] { - (new ChiselStage).emitChirrtl(new UserExceptionModule) - } - - info(s""" - Exception was a ${exception.getClass.getName}""") - - val message = exception.getMessage - info("The exception includes the user's message") - message should include("User threw an exception") - - val stackTrace = exception.getStackTrace.mkString("\n") - info("The stack trace is trimmed") - (stackTrace should not).include("java") - - info("The stack trace include information about running --full-stacktrace") - stackTrace should include("--full-stacktrace") - } - - it should """not truncate a user exception with "--full-stacktrace"""" in { - info("The user's java.lang.AssertionError was thrown") - val exception = intercept[java.lang.AssertionError] { - (new ChiselStage).emitChirrtl(new UserExceptionModule, Array("--full-stacktrace")) - } - - info(s""" - Exception was a ${exception.getClass.getName}""") - - val message = exception.getMessage - info("The exception includes the user's message") - message should include("User threw an exception") - - info("The stack trace is not trimmed") - exception.getStackTrace.mkString("\n") should include("java") - } - - it should "NOT add a stack trace to an exception with no stack trace" in { - val exception = intercept[java.lang.Exception] { - (new ChiselStage).emitChirrtl(new UserExceptionNoStackTrace) - } - - val message = exception.getMessage - info("The exception includes the user's message") - message should include("Something bad happened") - - info("The exception should not contain a stack trace") - exception.getStackTrace should be(Array()) - } - - it should "NOT include a stack trace for recoverable errors" in { - val exception = intercept[java.lang.Exception] { - (new ChiselStage).emitChirrtl(new RecoverableError) - } - - val message = exception.getMessage - info("The exception includes the standard error message") - message should include("Fatal errors during hardware elaboration. Look above for error list.") - - info("The exception should not contain a stack trace") - exception.getStackTrace should be(Array()) - } - - it should "include a stack trace for recoverable errors with '--throw-on-first-error'" in { - val exception = intercept[java.lang.Exception] { - (new ChiselStage).emitChirrtl(new RecoverableError, Array("--throw-on-first-error")) - } - - val stackTrace = exception.getStackTrace.mkString("\n") - info("The exception should contain a truncated stack trace") - stackTrace shouldNot include("java") - - info("The stack trace include information about running --full-stacktrace") - stackTrace should include("--full-stacktrace") - } - - it should "include an untruncated stack trace for recoverable errors when given both '--throw-on-first-error' and '--full-stacktrace'" in { - val exception = intercept[java.lang.Exception] { - val args = Array("--throw-on-first-error", "--full-stacktrace") - (new ChiselStage).emitChirrtl(new RecoverableError, args) - } - - val stackTrace = exception.getStackTrace.mkString("\n") - info("The exception should contain a truncated stack trace") - stackTrace should include("java") - } -} diff --git a/src/test/scala/chiselTests/stage/phases/AddImplicitOutputAnnotationFileSpec.scala b/src/test/scala/chiselTests/stage/phases/AddImplicitOutputAnnotationFileSpec.scala deleted file mode 100644 index faf411ed..00000000 --- a/src/test/scala/chiselTests/stage/phases/AddImplicitOutputAnnotationFileSpec.scala +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.stage.phases - -import chisel3.RawModule -import chisel3.stage.ChiselGeneratorAnnotation -import chisel3.stage.phases.{AddImplicitOutputAnnotationFile, Elaborate} - -import firrtl.AnnotationSeq -import firrtl.options.{OutputAnnotationFileAnnotation, Phase} -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers - -class AddImplicitOutputAnnotationFileSpec extends AnyFlatSpec with Matchers { - - class Foo extends RawModule { override val desiredName = "Foo" } - - class Fixture { val phase: Phase = new AddImplicitOutputAnnotationFile } - - behavior.of(classOf[AddImplicitOutputAnnotationFile].toString) - - it should "not override an existing OutputAnnotationFileAnnotation" in new Fixture { - val annotations: AnnotationSeq = - Seq(ChiselGeneratorAnnotation(() => new Foo), OutputAnnotationFileAnnotation("Bar")) - - Seq(new Elaborate, phase) - .foldLeft(annotations)((a, p) => p.transform(a)) - .collect { case a: OutputAnnotationFileAnnotation => a.file } - .toSeq should be(Seq("Bar")) - } - - it should "generate an OutputAnnotationFileAnnotation from a ChiselCircuitAnnotation" in new Fixture { - val annotations: AnnotationSeq = Seq(ChiselGeneratorAnnotation(() => new Foo)) - - Seq(new Elaborate, phase) - .foldLeft(annotations)((a, p) => p.transform(a)) - .collect { case a: OutputAnnotationFileAnnotation => a.file } - .toSeq should be(Seq("Foo")) - } - -} diff --git a/src/test/scala/chiselTests/stage/phases/AddImplicitOutputFileSpec.scala b/src/test/scala/chiselTests/stage/phases/AddImplicitOutputFileSpec.scala deleted file mode 100644 index 20274e7a..00000000 --- a/src/test/scala/chiselTests/stage/phases/AddImplicitOutputFileSpec.scala +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.stage.phases - -import chisel3.RawModule -import chisel3.stage.{ChiselGeneratorAnnotation, ChiselOutputFileAnnotation} -import chisel3.stage.phases.{AddImplicitOutputFile, Elaborate} - -import firrtl.AnnotationSeq -import firrtl.options.{Phase, StageOptions, TargetDirAnnotation} -import firrtl.options.Viewer.view -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers - -class AddImplicitOutputFileSpec extends AnyFlatSpec with Matchers { - - class Foo extends RawModule { override val desiredName = "Foo" } - - class Fixture { val phase: Phase = new AddImplicitOutputFile } - - behavior.of(classOf[AddImplicitOutputFile].toString) - - it should "not override an existing ChiselOutputFileAnnotation" in new Fixture { - val annotations: AnnotationSeq = Seq(ChiselGeneratorAnnotation(() => new Foo), ChiselOutputFileAnnotation("Bar")) - - Seq(new Elaborate, phase) - .foldLeft(annotations)((a, p) => p.transform(a)) - .collect { case a: ChiselOutputFileAnnotation => a.file } - .toSeq should be(Seq("Bar")) - } - - it should "generate a ChiselOutputFileAnnotation from a ChiselCircuitAnnotation" in new Fixture { - val annotations: AnnotationSeq = Seq(ChiselGeneratorAnnotation(() => new Foo), TargetDirAnnotation("test_run_dir")) - - Seq(new Elaborate, phase) - .foldLeft(annotations)((a, p) => p.transform(a)) - .collect { case a: ChiselOutputFileAnnotation => a.file } - .toSeq should be(Seq("Foo")) - } - - it should "do nothing to an empty annotation sequence" in new Fixture { - phase.transform(AnnotationSeq(Seq.empty)).toSeq should be(empty) - } - -} diff --git a/src/test/scala/chiselTests/stage/phases/AddSerializationAnnotationsSpec.scala b/src/test/scala/chiselTests/stage/phases/AddSerializationAnnotationsSpec.scala deleted file mode 100644 index 57633eac..00000000 --- a/src/test/scala/chiselTests/stage/phases/AddSerializationAnnotationsSpec.scala +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.stage.phases - -import chisel3.RawModule -import chisel3.stage.{ChiselGeneratorAnnotation, ChiselOutputFileAnnotation, CircuitSerializationAnnotation} -import chisel3.stage.CircuitSerializationAnnotation._ -import chisel3.stage.phases.{AddImplicitOutputFile, AddSerializationAnnotations, Elaborate} - -import firrtl.AnnotationSeq -import firrtl.options.{Dependency, Phase, PhaseManager, TargetDirAnnotation} -import firrtl.options.Viewer.view -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers - -class AddSerializationAnnotationsSpec extends AnyFlatSpec with Matchers { - - class Foo extends RawModule { override val desiredName = "Foo" } - - class Fixture { - val phase: Phase = new AddSerializationAnnotations - val manager = new PhaseManager(Dependency[AddSerializationAnnotations] :: Nil) - } - - behavior.of(classOf[AddSerializationAnnotations].toString) - - it should "default to FirrtlFileFormat" in new Fixture { - val annotations: AnnotationSeq = Seq(ChiselGeneratorAnnotation(() => new Foo), ChiselOutputFileAnnotation("Bar")) - - manager - .transform(annotations) - .collect { case CircuitSerializationAnnotation(_, filename, format) => (filename, format) } - .toSeq should be(Seq(("Bar", FirrtlFileFormat))) - } - - it should "support ProtoBufFileFormat" in new Fixture { - val annotations: AnnotationSeq = Seq(ChiselGeneratorAnnotation(() => new Foo), ChiselOutputFileAnnotation("Bar.pb")) - - manager - .transform(annotations) - .collect { case CircuitSerializationAnnotation(_, filename, format) => (filename, format) } - .toSeq should be(Seq(("Bar", ProtoBufFileFormat))) - } - - it should "support explicitly asking for FirrtlFileFormat" in new Fixture { - val annotations: AnnotationSeq = - Seq(ChiselGeneratorAnnotation(() => new Foo), ChiselOutputFileAnnotation("Bar.pb.fir")) - - manager - .transform(annotations) - .collect { case CircuitSerializationAnnotation(_, filename, format) => (filename, format) } - .toSeq should be(Seq(("Bar.pb", FirrtlFileFormat))) - } - -} diff --git a/src/test/scala/chiselTests/stage/phases/ChecksSpec.scala b/src/test/scala/chiselTests/stage/phases/ChecksSpec.scala deleted file mode 100644 index 3d42efdd..00000000 --- a/src/test/scala/chiselTests/stage/phases/ChecksSpec.scala +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.stage.phases - -import chisel3.stage.{ChiselOutputFileAnnotation, NoRunFirrtlCompilerAnnotation, PrintFullStackTraceAnnotation} -import chisel3.stage.phases.Checks - -import firrtl.AnnotationSeq -import firrtl.annotations.NoTargetAnnotation -import firrtl.options.{OptionsException, Phase} -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers - -class ChecksSpec extends AnyFlatSpec with Matchers { - - def checkExceptionMessage(phase: Phase, annotations: AnnotationSeq, messageStart: String): Unit = - intercept[OptionsException] { phase.transform(annotations) }.getMessage should startWith(messageStart) - - class Fixture { val phase: Phase = new Checks } - - behavior.of(classOf[Checks].toString) - - it should "do nothing on sane annotation sequences" in new Fixture { - val a = Seq(NoRunFirrtlCompilerAnnotation, PrintFullStackTraceAnnotation) - phase.transform(a).toSeq should be(a) - } - - it should "throw an OptionsException if more than one NoRunFirrtlCompilerAnnotation is specified" in new Fixture { - val a = Seq(NoRunFirrtlCompilerAnnotation, NoRunFirrtlCompilerAnnotation) - checkExceptionMessage(phase, a, "At most one NoRunFirrtlCompilerAnnotation") - } - - it should "throw an OptionsException if more than one PrintFullStackTraceAnnotation is specified" in new Fixture { - val a = Seq(PrintFullStackTraceAnnotation, PrintFullStackTraceAnnotation) - checkExceptionMessage(phase, a, "At most one PrintFullStackTraceAnnotation") - } - - it should "throw an OptionsException if more than one ChiselOutputFileAnnotation is specified" in new Fixture { - val a = Seq(ChiselOutputFileAnnotation("foo"), ChiselOutputFileAnnotation("bar")) - checkExceptionMessage(phase, a, "At most one Chisel output file") - } - -} diff --git a/src/test/scala/chiselTests/stage/phases/ConvertSpec.scala b/src/test/scala/chiselTests/stage/phases/ConvertSpec.scala deleted file mode 100644 index 46a2994b..00000000 --- a/src/test/scala/chiselTests/stage/phases/ConvertSpec.scala +++ /dev/null @@ -1,65 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.stage.phases - -import chisel3._ -import chisel3.experimental.{ChiselAnnotation, RunFirrtlTransform} -import chisel3.stage.ChiselGeneratorAnnotation -import chisel3.stage.phases.{Convert, Elaborate} - -import firrtl.{AnnotationSeq, CircuitForm, CircuitState, DependencyAPIMigration, Transform, UnknownForm} -import firrtl.annotations.{Annotation, NoTargetAnnotation} -import firrtl.options.Phase -import firrtl.stage.{FirrtlCircuitAnnotation, RunFirrtlTransformAnnotation} -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers - -class ConvertSpecFirrtlTransform extends Transform with DependencyAPIMigration { - override def prerequisites = Seq.empty - override def optionalPrerequisites = Seq.empty - override def optionalPrerequisiteOf = Seq.empty - override def invalidates(a: Transform) = false - def execute(state: CircuitState): CircuitState = state -} - -case class ConvertSpecFirrtlAnnotation(name: String) extends NoTargetAnnotation - -case class ConvertSpecChiselAnnotation(name: String) extends ChiselAnnotation with RunFirrtlTransform { - def toFirrtl: Annotation = ConvertSpecFirrtlAnnotation(name) - def transformClass: Class[_ <: Transform] = classOf[ConvertSpecFirrtlTransform] -} - -class ConvertSpecFoo extends RawModule { - override val desiredName: String = "foo" - - val in = IO(Input(Bool())) - val out = IO(Output(Bool())) - - experimental.annotate(ConvertSpecChiselAnnotation("bar")) -} - -class ConvertSpec extends AnyFlatSpec with Matchers { - - class Fixture { val phase: Phase = new Convert } - - behavior.of(classOf[Convert].toString) - - it should "convert a Chisel Circuit to a FIRRTL Circuit" in new Fixture { - val annos: AnnotationSeq = Seq(ChiselGeneratorAnnotation(() => new ConvertSpecFoo)) - - val annosx = Seq(new Elaborate, phase) - .foldLeft(annos)((a, p) => p.transform(a)) - - info("FIRRTL circuit generated") - annosx.collect { case a: FirrtlCircuitAnnotation => a.circuit.main }.toSeq should be(Seq("foo")) - - info("FIRRTL annotations generated") - annosx.collect { case a: ConvertSpecFirrtlAnnotation => a.name }.toSeq should be(Seq("bar")) - - info("FIRRTL transform annotations generated") - annosx.collect { case a: RunFirrtlTransformAnnotation => a.transform.getClass }.toSeq should be( - Seq(classOf[ConvertSpecFirrtlTransform]) - ) - } - -} diff --git a/src/test/scala/chiselTests/stage/phases/ElaborateSpec.scala b/src/test/scala/chiselTests/stage/phases/ElaborateSpec.scala deleted file mode 100644 index 90bb229b..00000000 --- a/src/test/scala/chiselTests/stage/phases/ElaborateSpec.scala +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.stage.phases - -import chisel3._ -import chisel3.stage.{ChiselCircuitAnnotation, ChiselGeneratorAnnotation} -import chisel3.stage.phases.Elaborate - -import firrtl.options.Phase -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers - -class ElaborateSpec extends AnyFlatSpec with Matchers { - - class Foo extends Module { - override def desiredName: String = "Foo" - val io = IO(new Bundle { - val in = Input(Bool()) - val out = Output(Bool()) - }) - - io.out := ~io.in - } - - class Bar extends Foo { - override def desiredName: String = "Bar" - } - - class Fixture { val phase: Phase = new Elaborate } - - behavior.of(classOf[Elaborate].toString) - - it should "expand ChiselGeneratorAnnotations into ChiselCircuitAnnotations and delete originals" in new Fixture { - val annotations = Seq(ChiselGeneratorAnnotation(() => new Foo), ChiselGeneratorAnnotation(() => new Bar)) - val out = phase.transform(annotations) - - info("original annotations removed") - out.collect { case a: ChiselGeneratorAnnotation => a } should be(empty) - - info("circuits created with the expected names") - out.collect { case a: ChiselCircuitAnnotation => a.circuit.name } should be(Seq("Foo", "Bar")) - } - -} diff --git a/src/test/scala/chiselTests/stage/phases/EmitterSpec.scala b/src/test/scala/chiselTests/stage/phases/EmitterSpec.scala deleted file mode 100644 index 9b7d4f42..00000000 --- a/src/test/scala/chiselTests/stage/phases/EmitterSpec.scala +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.stage.phases - -import chisel3.RawModule -import chisel3.stage.{ChiselCircuitAnnotation, ChiselGeneratorAnnotation, ChiselOutputFileAnnotation} -import chisel3.stage.phases.{Convert, Elaborate, Emitter} - -import firrtl.{AnnotationSeq, EmittedFirrtlCircuitAnnotation} -import firrtl.annotations.DeletedAnnotation -import firrtl.options.{Phase, TargetDirAnnotation} - -import java.io.File -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers - -class EmitterSpec extends AnyFlatSpec with Matchers { - - class FooModule extends RawModule { override val desiredName = "Foo" } - class BarModule extends RawModule { override val desiredName = "Bar" } - - class Fixture { val phase: Phase = new Emitter } - - behavior.of(classOf[Emitter].toString) - - it should "do nothing if no ChiselOutputFileAnnotations are present" in new Fixture { - val dir = new File("test_run_dir/EmitterSpec") - val annotations = - (new Elaborate).transform(Seq(TargetDirAnnotation(dir.toString), ChiselGeneratorAnnotation(() => new FooModule))) - val annotationsx = phase.transform(annotations) - - val Seq(fooFile, barFile) = Seq("Foo.fir", "Bar.fir").map(f => new File(dir + "/" + f)) - - info(s"$fooFile does not exist") - fooFile should not(exist) - - info("annotations are unmodified") - annotationsx.toSeq should be(annotations.toSeq) - } - - it should "emit a ChiselCircuitAnnotation to a specific file" in new Fixture { - val dir = new File("test_run_dir/EmitterSpec") - val circuit = (new Elaborate) - .transform(Seq(ChiselGeneratorAnnotation(() => new BarModule))) - .collectFirst { case a: ChiselCircuitAnnotation => a } - .get - val annotations = - phase.transform(Seq(TargetDirAnnotation(dir.toString), circuit, ChiselOutputFileAnnotation("Baz"))) - - val bazFile = new File(dir + "/Baz.fir") - - info(s"$bazFile exists") - bazFile should (exist) - - info("a deleted EmittedFirrtlCircuitAnnotation should be generated") - annotations.collect { case a @ DeletedAnnotation(_, _: EmittedFirrtlCircuitAnnotation) => a }.size should be(1) - } - -} diff --git a/src/test/scala/chiselTests/util/BitPatSpec.scala b/src/test/scala/chiselTests/util/BitPatSpec.scala deleted file mode 100644 index 38ffc3ba..00000000 --- a/src/test/scala/chiselTests/util/BitPatSpec.scala +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.util - -import chisel3.util.BitPat -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers - -class BitPatSpec extends AnyFlatSpec with Matchers { - behavior.of(classOf[BitPat].toString) - - it should "convert a BitPat to readable form" in { - val testPattern = "0" * 32 + "1" * 32 + "?" * 32 + "?01" * 32 - BitPat("b" + testPattern).toString should be(s"BitPat($testPattern)") - } - - it should "convert a BitPat to raw form" in { - val testPattern = "0" * 32 + "1" * 32 + "?" * 32 + "?01" * 32 - BitPat("b" + testPattern).rawString should be(testPattern) - } - - it should "not fail if BitPat width is 0" in { - intercept[IllegalArgumentException] { BitPat("b") } - } - - it should "concat BitPat via ##" in { - (BitPat.Y(4) ## BitPat.dontCare(3) ## BitPat.N(2)).toString should be(s"BitPat(1111???00)") - } - - it should "throw when BitPat apply to a Hardware" in { - intercept[java.lang.IllegalArgumentException] { - chisel3.stage.ChiselStage.emitChirrtl(new chisel3.Module { - BitPat(chisel3.Reg(chisel3.Bool())) - }) - } - } - - it should "index and return new BitPat" in { - val b = BitPat("b1001???") - b(0) should be(BitPat.dontCare(1)) - b(6) should be(BitPat.Y()) - b(5) should be(BitPat.N()) - } - - it should "slice and return new BitPat" in { - val b = BitPat("b1001???") - b(2, 0) should be(BitPat("b???")) - b(4, 3) should be(BitPat("b01")) - b(6, 6) should be(BitPat("b1")) - } -} diff --git a/src/test/scala/chiselTests/util/BitSetSpec.scala b/src/test/scala/chiselTests/util/BitSetSpec.scala deleted file mode 100644 index cf5f54cf..00000000 --- a/src/test/scala/chiselTests/util/BitSetSpec.scala +++ /dev/null @@ -1,145 +0,0 @@ -package chiselTests.util - -import chisel3.util.experimental.BitSet -import chisel3.util.BitPat -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers - -class BitSetSpec extends AnyFlatSpec with Matchers { - behavior.of(classOf[BitSet].toString) - - it should "reject unequal width when constructing a BitSet" in { - intercept[IllegalArgumentException] { - BitSet.fromString("""b0010 - |b00010 - |""".stripMargin) - } - } - - it should "return empty subtraction result correctly" in { - val aBitPat = BitPat("b10?") - val bBitPat = BitPat("b1??") - - aBitPat.subtract(bBitPat).isEmpty should be(true) - } - - it should "return nonempty subtraction result correctly" in { - val aBitPat = BitPat("b10?") - val bBitPat = BitPat("b1??") - val cBitPat = BitPat("b11?") - val dBitPat = BitPat("b100") - - val diffBitPat = bBitPat.subtract(aBitPat) - bBitPat.cover(diffBitPat) should be(true) - diffBitPat.equals(cBitPat) should be(true) - - val largerdiffBitPat = bBitPat.subtract(dBitPat) - aBitPat.cover(dBitPat) should be(true) - largerdiffBitPat.cover(diffBitPat) should be(true) - } - - it should "be able to handle complex subtract between BitSet" in { - val aBitSet = BitSet.fromString("""b?01?0 - |b11111 - |b00000 - |""".stripMargin) - val bBitSet = BitSet.fromString( - """b?1111 - |b?0000 - |""".stripMargin - ) - val expected = BitPat("b?01?0") - - expected.equals(aBitSet.subtract(bBitSet)) should be(true) - } - - it should "be generated from BitPat union" in { - val aBitSet = BitSet.fromString("""b001?0 - |b000??""".stripMargin) - val aBitPat = BitPat("b000??") - val bBitPat = BitPat("b001?0") - val cBitPat = BitPat("b00000") - aBitPat.cover(cBitPat) should be(true) - aBitSet.cover(bBitPat) should be(true) - - aBitSet.equals(aBitPat.union(bBitPat)) should be(true) - } - - it should "be generated from BitPat subtraction" in { - val aBitSet = BitSet.fromString("""b001?0 - |b000??""".stripMargin) - val aBitPat = BitPat("b00???") - val bBitPat = BitPat("b001?1") - - aBitSet.equals(aBitPat.subtract(bBitPat)) should be(true) - } - - it should "union two BitSet together" in { - val aBitSet = BitSet.fromString("""b001?0 - |b001?1 - |""".stripMargin) - val bBitSet = BitSet.fromString( - """b000?? - |b01??? - |""".stripMargin - ) - val cBitPat = BitPat("b0????") - cBitPat.equals(aBitSet.union(bBitSet)) should be(true) - } - - it should "be decoded" in { - import chisel3._ - import chisel3.util.experimental.decode.decoder - // [0 - 256] part into: [0 - 31], [32 - 47, 64 - 127], [192 - 255] - // "0011????" "10??????" is empty to error - chisel3.stage.ChiselStage.emitSystemVerilog(new Module { - val in = IO(Input(UInt(8.W))) - val out = IO(Output(UInt(4.W))) - out := decoder.bitset( - in, - Seq( - BitSet.fromString( - "b000?????" - ), - BitSet.fromString( - """b0010???? - |b01?????? - |""".stripMargin - ), - BitSet.fromString( - "b11??????" - ) - ), - errorBit = true - ) - }) - } - - it should "be decoded with DontCare error" in { - import chisel3._ - import chisel3.util.experimental.decode.decoder - // [0 - 256] part into: [0 - 31], [32 - 47, 64 - 127], [192 - 255] - // "0011????" "10??????" is empty to error - chisel3.stage.ChiselStage.emitSystemVerilog(new Module { - val in = IO(Input(UInt(8.W))) - val out = IO(Output(UInt(4.W))) - out := decoder.bitset( - in, - Seq( - BitSet.fromString( - "b000?????" - ), - BitSet.fromString( - """b0010???? - |b01?????? - |""".stripMargin - ), - BitSet.fromString( - "b11??????" - ) - ), - errorBit = false - ) - }) - } -} diff --git a/src/test/scala/chiselTests/util/CatSpec.scala b/src/test/scala/chiselTests/util/CatSpec.scala deleted file mode 100644 index a75c4ec0..00000000 --- a/src/test/scala/chiselTests/util/CatSpec.scala +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.util - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.util.Cat -import chisel3.experimental.noPrefix - -import chiselTests.ChiselFlatSpec - -object CatSpec { - - class JackIsATypeSystemGod extends Module { - val in = IO(Input(Vec(0, UInt(8.W)))) - val out = IO(Output(UInt(8.W))) - - out := Cat(in) - } - -} - -class CatSpec extends ChiselFlatSpec { - - import CatSpec._ - - behavior.of("util.Cat") - - it should "not fail to elaborate a zero-element Vec" in { - - ChiselStage.elaborate(new JackIsATypeSystemGod) - - } - - it should "not override the names of its arguments" in { - class MyModule extends RawModule { - val a, b, c, d = IO(Input(UInt(8.W))) - val out = IO(Output(UInt())) - - out := Cat(a, b, c, d) - } - val chirrtl = ChiselStage.emitChirrtl(new MyModule) - for (name <- Seq("a", "b", "c", "d")) { - chirrtl should include(s"input $name : UInt<8>") - } - } - - it should "have prefixed naming" in { - class MyModule extends RawModule { - val in = IO(Input(Vec(8, UInt(8.W)))) - val out = IO(Output(UInt())) - - // noPrefix to avoid `out` as prefix - out := noPrefix(Cat(in)) - } - val chirrtl = ChiselStage.emitChirrtl(new MyModule) - chirrtl should include("node lo_lo = cat(in[6], in[7])") - chirrtl should include("node lo_hi = cat(in[4], in[5])") - chirrtl should include("node hi_lo = cat(in[2], in[3])") - chirrtl should include("node hi_hi = cat(in[0], in[1])") - } - -} diff --git a/src/test/scala/chiselTests/util/PriorityMuxSpec.scala b/src/test/scala/chiselTests/util/PriorityMuxSpec.scala deleted file mode 100644 index 32cf2431..00000000 --- a/src/test/scala/chiselTests/util/PriorityMuxSpec.scala +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.util - -import chisel3._ -import chisel3.util.{is, switch, Counter, PriorityMux} -import chisel3.testers.BasicTester -import chisel3.stage.ChiselStage.emitChirrtl - -import chiselTests.ChiselFlatSpec - -class PriorityMuxTester extends BasicTester { - - val sel = Wire(UInt(3.W)) - sel := 0.U // default - - val elts = Seq(5.U, 6.U, 7.U) - val muxed = PriorityMux(sel, elts) - - // Priority is given to lowest order bit - val tests = Seq( - 1.U -> elts(0), - 2.U -> elts(1), - 3.U -> elts(0), - 4.U -> elts(2), - 5.U -> elts(0), - 6.U -> elts(1), - 7.U -> elts(0) - ) - val (cycle, done) = Counter(0 until tests.size + 1) - - for (((in, out), idx) <- tests.zipWithIndex) { - when(cycle === idx.U) { - sel := in - assert(muxed === out) - } - } - - when(done) { - stop() - } -} - -class PriorityMuxSpec extends ChiselFlatSpec { - behavior.of("PriorityMux") - - it should "be functionally correct" in { - assertTesterPasses(new PriorityMuxTester) - } - - it should "be stack safe" in { - emitChirrtl(new RawModule { - val n = 1 << 15 - val in = IO(Input(Vec(n, UInt(8.W)))) - val sel = IO(Input(UInt(n.W))) - val out = IO(Output(UInt(8.W))) - out := PriorityMux(sel, in) - }) - } -} diff --git a/src/test/scala/chiselTests/util/experimental/PlaSpec.scala b/src/test/scala/chiselTests/util/experimental/PlaSpec.scala deleted file mode 100644 index 156249a2..00000000 --- a/src/test/scala/chiselTests/util/experimental/PlaSpec.scala +++ /dev/null @@ -1,111 +0,0 @@ -package chiselTests.util.experimental - -import chisel3._ -import chisel3.stage.PrintFullStackTraceAnnotation -import chisel3.testers.BasicTester -import chisel3.util.{pla, BitPat} -import chiselTests.ChiselFlatSpec - -class PlaSpec extends ChiselFlatSpec { - "A 1-of-8 decoder (eg. 74xx138 without enables)" should "be generated correctly" in { - assertTesterPasses(new BasicTester { - val table = Seq( - (BitPat("b000"), BitPat("b00000001")), - (BitPat("b001"), BitPat("b00000010")), - (BitPat("b010"), BitPat("b00000100")), - (BitPat("b011"), BitPat("b00001000")), - (BitPat("b100"), BitPat("b00010000")), - (BitPat("b101"), BitPat("b00100000")), - (BitPat("b110"), BitPat("b01000000")), - (BitPat("b111"), BitPat("b10000000")) - ) - table.foreach { - case (i, o) => - val (plaIn, plaOut) = pla(table) - plaIn := WireDefault(i.value.U(3.W)) - chisel3.assert( - plaOut === o.value.U(8.W), - "Input " + i.toString + " produced incorrect output BitPat(%b)", - plaOut - ) - } - stop() - }) - } - - "An active-low 1-of-8 decoder (eg. inverted 74xx138 without enables)" should "be generated correctly" in { - assertTesterPasses(new BasicTester { - val table = Seq( - (BitPat("b000"), BitPat("b00000001")), - (BitPat("b001"), BitPat("b00000010")), - (BitPat("b010"), BitPat("b00000100")), - (BitPat("b011"), BitPat("b00001000")), - (BitPat("b100"), BitPat("b00010000")), - (BitPat("b101"), BitPat("b00100000")), - (BitPat("b110"), BitPat("b01000000")), - (BitPat("b111"), BitPat("b10000000")) - ) - table.foreach { - case (i, o) => - val (plaIn, plaOut) = pla(table, BitPat("b11111111")) - plaIn := WireDefault(i.value.U(3.W)) - chisel3.assert( - plaOut === ~o.value.U(8.W), - "Input " + i.toString + " produced incorrect output BitPat(%b)", - plaOut - ) - } - stop() - }) - } - - "#2112" should "be generated correctly" in { - assertTesterPasses(new BasicTester { - val table = Seq( - (BitPat("b000"), BitPat("b?01")), - (BitPat("b111"), BitPat("b?01")) - ) - table.foreach { - case (i, o) => - val (plaIn, plaOut) = pla(table) - plaIn := WireDefault(i.value.U(3.W)) - chisel3.assert(o === plaOut, "Input " + i.toString + " produced incorrect output BitPat(%b)", plaOut) - } - stop() - }) - } - - "A simple PLA" should "be generated correctly" in { - assertTesterPasses(new BasicTester { - val table = Seq( - (BitPat("b0000"), BitPat("b1")), - (BitPat("b0001"), BitPat("b1")), - (BitPat("b0010"), BitPat("b0")), - (BitPat("b0011"), BitPat("b1")), - (BitPat("b0100"), BitPat("b1")), - (BitPat("b0101"), BitPat("b0")), - (BitPat("b0110"), BitPat("b0")), - (BitPat("b0111"), BitPat("b0")), - (BitPat("b1000"), BitPat("b0")), - (BitPat("b1001"), BitPat("b0")), - (BitPat("b1010"), BitPat("b1")), - (BitPat("b1011"), BitPat("b0")), - (BitPat("b1100"), BitPat("b0")), - (BitPat("b1101"), BitPat("b1")), - (BitPat("b1110"), BitPat("b1")), - (BitPat("b1111"), BitPat("b1")) - ) - table.foreach { - case (i, o) => - val (plaIn, plaOut) = pla(table) - plaIn := WireDefault(i.value.U(4.W)) - chisel3.assert( - plaOut === o.value.U(1.W), - "Input " + i.toString + " produced incorrect output BitPat(%b)", - plaOut - ) - } - stop() - }) - } -} diff --git a/src/test/scala/chiselTests/util/experimental/TruthTableSpec.scala b/src/test/scala/chiselTests/util/experimental/TruthTableSpec.scala deleted file mode 100644 index b5dcee6b..00000000 --- a/src/test/scala/chiselTests/util/experimental/TruthTableSpec.scala +++ /dev/null @@ -1,126 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.util.experimental - -import chisel3._ -import chisel3.util.BitPat -import chisel3.util.experimental.decode.{decoder, TruthTable} -import org.scalatest.flatspec.AnyFlatSpec - -class TruthTableSpec extends AnyFlatSpec { - val table = TruthTable( - Map( - // BitPat("b000") -> BitPat("b0"), - BitPat("b001") -> BitPat("b?"), - BitPat("b010") -> BitPat("b?"), - // BitPat("b011") -> BitPat("b0"), - BitPat("b100") -> BitPat("b1"), - BitPat("b101") -> BitPat("b1"), - // BitPat("b110") -> BitPat("b0"), - BitPat("b111") -> BitPat("b1") - ), - BitPat("b0") - ) - val str = """001->? - |010->? - |100->1 - |101->1 - |111->1 - |0""".stripMargin - "TruthTable" should "serialize" in { - assert(table.toString contains "001->?") - assert(table.toString contains "010->?") - assert(table.toString contains "100->1") - assert(table.toString contains "111->1") - assert(table.toString contains " 0") - } - "TruthTable" should "deserialize" in { - val table2 = TruthTable.fromString(str) - assert(table2 === table) - assert(table2.hashCode === table.hashCode) - } - "TruthTable" should "merge same key" in { - assert( - TruthTable.fromString( - """001100->??1 - |001100->1?? - |??? - |""".stripMargin - ) == TruthTable.fromString( - """001100->1?1 - |??? - |""".stripMargin - ) - ) - } - "TruthTable" should "crash when merging 0 and 1" in { - intercept[IllegalArgumentException] { - TruthTable.fromString( - """0->0 - |0->1 - |??? - |""".stripMargin - ) - } - } - "TruthTable" should "be reproducible" in { - class Foo extends Module { - - val io = IO(new Bundle { - val in = Input(UInt(4.W)) - val out = Output(UInt(16.W)) - }) - - val table = TruthTable( - (0 until 16).map { i => - BitPat(i.U(4.W)) -> BitPat((1 << i).U(16.W)) - }, - BitPat.dontCare(16) - ) - - io.out := decoder.qmc(io.in, table) - } - assert(chisel3.stage.ChiselStage.emitChirrtl(new Foo) == chisel3.stage.ChiselStage.emitChirrtl(new Foo)) - } - "TruthTable" should "accept unknown input width" in { - val t = TruthTable( - Seq( - BitPat(0.U) -> BitPat.dontCare(1), - BitPat(1.U) -> BitPat.dontCare(1), - BitPat(2.U) -> BitPat.dontCare(1), - BitPat(3.U) -> BitPat.dontCare(1), - BitPat(4.U) -> BitPat.dontCare(1), - BitPat(5.U) -> BitPat.dontCare(1), - BitPat(6.U) -> BitPat.dontCare(1), - BitPat(7.U) -> BitPat.dontCare(1) - ), - BitPat.N(1) - ) - assert(t.toString contains "000->?") - assert(t.toString contains "001->?") - assert(t.toString contains "010->?") - assert(t.toString contains "011->?") - assert(t.toString contains "100->?") - assert(t.toString contains "101->?") - assert(t.toString contains "110->?") - assert(t.toString contains "111->?") - assert(t.toString contains " 0") - } - - "Using TruthTable.fromEspressoOutput" should "merge rows on conflict" in { - val mapping = List( - (BitPat("b110"), BitPat("b001")), - (BitPat("b111"), BitPat("b001")), - (BitPat("b111"), BitPat("b010")), - (BitPat("b111"), BitPat("b100")) - ) - - assert( - TruthTable.fromEspressoOutput(mapping, BitPat("b?")) == - TruthTable.fromString("""110->001 - |111->111 - |? - |""".stripMargin) - ) - } -} diff --git a/src/test/scala/chiselTests/util/random/LFSRSpec.scala b/src/test/scala/chiselTests/util/random/LFSRSpec.scala deleted file mode 100644 index d47c2d7d..00000000 --- a/src/test/scala/chiselTests/util/random/LFSRSpec.scala +++ /dev/null @@ -1,182 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.util.random - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.util.{Cat, Counter, Enum} -import chisel3.util.random._ -import chisel3.testers.{BasicTester, TesterDriver} -import chiselTests.{ChiselFlatSpec, Utils} - -import math.pow - -class FooLFSR(val reduction: LFSRReduce, seed: Option[BigInt]) extends PRNG(4, seed) with LFSR { - def delta(s: Seq[Bool]): Seq[Bool] = s -} - -class LFSRMaxPeriod(gen: => UInt) extends BasicTester { - - val rv = gen - val started = RegNext(true.B, false.B) - val seed = withReset(!started) { RegInit(rv) } - - val (_, wrap) = Counter(started, math.pow(2.0, rv.getWidth).toInt - 1) - - when(rv === seed && started) { - chisel3.assert(wrap) - stop() - } - - val last = RegNext(rv) - chisel3.assert(rv =/= last, "LFSR last value (0b%b) was equal to current value (0b%b)", rv, last) - -} - -/** - * This test creates two 4 sided dice. - * Each cycle it adds them together and adds a count to the bin corresponding to that value - * The asserts check that the bins show the correct distribution. - */ -class LFSRDistribution(gen: => UInt, cycles: Int = 10000) extends BasicTester { - - val rv = gen - val bins = Reg(Vec(8, UInt(32.W))) - - // Use tap points on each LFSR so values are more independent - val die0 = Cat(Seq.tabulate(2) { i => rv(i) }) - val die1 = Cat(Seq.tabulate(2) { i => rv(i + 2) }) - - val (trial, done) = Counter(true.B, cycles) - - val rollValue = die0 +& die1 // Note +& is critical because sum will need an extra bit. - - bins(rollValue) := bins(rollValue) + 1.U - - when(done) { - printf(p"bins: $bins\n") // Note using the printable interpolator p"" to print out a Vec - - // test that the distribution feels right. - assert(bins(1) > bins(0)) - assert(bins(2) > bins(1)) - assert(bins(3) > bins(2)) - assert(bins(4) < bins(3)) - assert(bins(5) < bins(4)) - assert(bins(6) < bins(5)) - assert(bins(7) === 0.U) - - stop() - } -} - -/** This tests that after reset an LFSR is not locked up. This manually sets the seed of the LFSR at run-time to the - * value that would cause it to lock up. It then asserts reset. The next cycle it checks that the value is NOT the - * locked up value. - * @param gen an LFSR to test - * @param lockUpValue the value that would lock up the LFSR - */ -class LFSRResetTester(gen: => LFSR, lockUpValue: BigInt) extends BasicTester { - - val lfsr = Module(gen) - lfsr.io.seed.valid := false.B - lfsr.io.seed.bits := DontCare - lfsr.io.increment := true.B - - val (count, done) = Counter(true.B, 5) - - lfsr.io.seed.valid := count === 1.U - lfsr.io.seed.bits := lockUpValue.U(lfsr.width.W).asBools - lfsr.io.increment := true.B - - when(count === 2.U) { - assert(lfsr.io.out.asUInt === lockUpValue.U, "LFSR is NOT locked up, but should be!") - } - - lfsr.reset := count === 3.U - - when(count === 4.U) { - assert(lfsr.io.out.asUInt =/= lockUpValue.U, "LFSR is locked up, but should not be after reset!") - } - - when(done) { - stop() - } - -} - -class LFSRSpec extends ChiselFlatSpec with Utils { - - def periodCheck(gen: (Int, Set[Int], LFSRReduce) => PRNG, reduction: LFSRReduce, range: Range): Unit = { - val testName = s"have a maximal period over a range of widths (${range.head} to ${range.last})" + - s" using ${reduction.getClass}" - it should testName in { - range.foreach { width => - LFSR.tapsMaxPeriod(width).foreach { taps => - info(s"""width $width okay using taps: ${taps.mkString(", ")}""") - assertTesterPasses( - new LFSRMaxPeriod(PRNG(gen(width, taps, reduction))), - annotations = TesterDriver.verilatorOnly - ) - } - } - } - } - - behavior.of("LFSR") - - it should "throw an exception if initialized to a seed of zero for XOR configuration" in { - { - the[IllegalArgumentException] thrownBy extractCause[IllegalArgumentException] { - ChiselStage.elaborate(new FooLFSR(XOR, Some(0))) - } - }.getMessage should include("Seed cannot be zero") - } - - it should "throw an exception if initialized to a seed of all ones for XNOR configuration" in { - { - the[IllegalArgumentException] thrownBy extractCause[IllegalArgumentException] { - ChiselStage.elaborate(new FooLFSR(XNOR, Some(15))) - } - }.getMessage should include("Seed cannot be all ones") - } - - it should "reset correctly without a seed for XOR configuration" in { - assertTesterPasses(new LFSRResetTester(new FooLFSR(XOR, None), 0)) - } - - it should "reset correctly without a seed for XNOR configuration" in { - assertTesterPasses(new LFSRResetTester(new FooLFSR(XNOR, None), 15)) - } - - behavior.of("MaximalPeriodGaloisLFSR") - - it should "throw an exception if no LFSR taps are known" in { - { - the[IllegalArgumentException] thrownBy extractCause[IllegalArgumentException] { - ChiselStage.elaborate(new MaxPeriodGaloisLFSR(787)) - } - }.getMessage should include("No max period LFSR taps stored for requested width") - } - - periodCheck((w: Int, t: Set[Int], r: LFSRReduce) => new GaloisLFSR(w, t, reduction = r), XOR, 2 to 16) - periodCheck((w: Int, t: Set[Int], r: LFSRReduce) => new GaloisLFSR(w, t, reduction = r), XNOR, 2 to 16) - - ignore should "have a sane distribution for larger widths" in { - ((17 to 32) ++ Seq(64, 128, 256, 512, 1024, 2048, 4096)).foreach { width => - info(s"width $width okay!") - assertTesterPasses(new LFSRDistribution(LFSR(width), math.pow(2, 22).toInt)) - } - } - - behavior.of("MaximalPeriodFibonacciLFSR") - - periodCheck((w: Int, t: Set[Int], r: LFSRReduce) => new FibonacciLFSR(w, t, reduction = r), XOR, 2 to 16) - periodCheck((w: Int, t: Set[Int], r: LFSRReduce) => new FibonacciLFSR(w, t, reduction = r), XNOR, 2 to 16) - - behavior.of("LFSR maximal period taps") - - it should "contain all the expected widths" in { - ((2 to 786) ++ Seq(1024, 2048, 4096)).foreach(LFSR.tapsMaxPeriod.keys should contain(_)) - } - -} diff --git a/src/test/scala/chiselTests/util/random/PRNGSpec.scala b/src/test/scala/chiselTests/util/random/PRNGSpec.scala deleted file mode 100644 index 36fdf9cb..00000000 --- a/src/test/scala/chiselTests/util/random/PRNGSpec.scala +++ /dev/null @@ -1,97 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chiselTests.util.random - -import chisel3._ -import chisel3.stage.ChiselStage -import chisel3.testers.BasicTester -import chisel3.util.Counter -import chisel3.util.random.PRNG - -import chiselTests.{ChiselFlatSpec, Utils} - -class CyclePRNG(width: Int, seed: Option[BigInt], step: Int, updateSeed: Boolean) - extends PRNG(width, seed, step, updateSeed) { - - def delta(s: Seq[Bool]): Seq[Bool] = s.last +: s.dropRight(1) - -} - -class PRNGStepTest extends BasicTester { - - val count2: UInt = Counter(true.B, 2)._1 - val count4: UInt = Counter(true.B, 4)._1 - - val a: UInt = PRNG(new CyclePRNG(16, Some(1), 1, false), true.B) - val b: UInt = PRNG(new CyclePRNG(16, Some(1), 2, false), count2 === 1.U) - val c: UInt = PRNG(new CyclePRNG(16, Some(1), 4, false), count4 === 3.U) - - val (_, done) = Counter(true.B, 16) - - when(count2 === 0.U) { - assert(a === b, "1-step and 2-step PRNGs did not agree! (0b%b != 0b%b)", a, b) - } - - when(count4 === 0.U) { - assert(a === c, "1-step and 4-step PRNGs did not agree!") - } - - when(done) { - stop() - } - -} - -class PRNGUpdateSeedTest(updateSeed: Boolean, seed: BigInt, expected: BigInt) extends BasicTester { - - val a: CyclePRNG = Module(new CyclePRNG(16, Some(1), 1, updateSeed)) - - val (count, done) = Counter(true.B, 4) - - a.io.increment := true.B - a.io.seed.valid := count === 2.U - a.io.seed.bits := seed.U(a.width.W).asBools - - when(count === 3.U) { - assert(a.io.out.asUInt === expected.U, "Output didn't match!") - } - - when(done) { - stop() - } - -} - -class PRNGSpec extends ChiselFlatSpec with Utils { - - behavior.of("PRNG") - - it should "throw an exception if the step size is < 1" in { - { - the[IllegalArgumentException] thrownBy extractCause[IllegalArgumentException] { - ChiselStage.elaborate(new CyclePRNG(0, Some(1), 1, true)) - } - }.getMessage should include("Width must be greater than zero!") - } - - it should "throw an exception if the step size is <= 0" in { - { - the[IllegalArgumentException] thrownBy extractCause[IllegalArgumentException] { - ChiselStage.elaborate(new CyclePRNG(1, Some(1), 0, true)) - } - }.getMessage should include("Step size must be greater than one!") - } - - it should "handle non-unary steps" in { - assertTesterPasses(new PRNGStepTest) - } - - it should "handle state update without and with updateSeed enabled" in { - info("without updateSeed okay!") - assertTesterPasses(new PRNGUpdateSeedTest(false, 3, 3)) - - info("with updateSeed okay!") - assertTesterPasses(new PRNGUpdateSeedTest(true, 3, 6)) - } - -} diff --git a/src/test/scala/cookbook/Bundle2UInt.scala b/src/test/scala/cookbook/Bundle2UInt.scala deleted file mode 100644 index 21d06df7..00000000 --- a/src/test/scala/cookbook/Bundle2UInt.scala +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package cookbook - -import chisel3._ - -/* ### How do I create a UInt from an instance of a Bundle? - * - * Call asUInt on the Bundle instance - */ -class Bundle2UInt extends CookbookTester(1) { - // Example - class MyBundle extends Bundle { - val foo = UInt(4.W) - val bar = UInt(4.W) - } - val bundle = Wire(new MyBundle) - bundle.foo := 0xc.U - bundle.bar := 0x3.U - val uint = bundle.asUInt - printf(p"$uint") // 195 - - // Test - assert(uint === 0xc3.U) -} - -class Bundle2UIntSpec extends CookbookSpec { - "Bundle2UInt" should "work" in { - assertTesterPasses { new Bundle2UInt } - } -} diff --git a/src/test/scala/cookbook/CookbookSpec.scala b/src/test/scala/cookbook/CookbookSpec.scala deleted file mode 100644 index 7d6c9726..00000000 --- a/src/test/scala/cookbook/CookbookSpec.scala +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package cookbook - -import chisel3._ -import chisel3.util._ -import chisel3.testers.BasicTester - -import chiselTests.ChiselFlatSpec - -/** Tester for concise cookbook tests - * - * Provides a length of test after which the test will pass - */ -abstract class CookbookTester(length: Int) extends BasicTester { - require(length >= 0, "Simulation length must be non-negative!") - - val (cycle, done) = Counter(true.B, length + 1) // + 1 cycle because done is actually wrap - when(done) { stop() } -} - -abstract class CookbookSpec extends ChiselFlatSpec diff --git a/src/test/scala/cookbook/FSM.scala b/src/test/scala/cookbook/FSM.scala deleted file mode 100644 index 40f8abc7..00000000 --- a/src/test/scala/cookbook/FSM.scala +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package cookbook - -import chisel3._ -import chisel3.util._ - -/* ### How do I create a finite state machine? - * - * Use ChiselEnum to construct the states and switch & is to construct the FSM - * control logic - */ - -class DetectTwoOnes extends Module { - val io = IO(new Bundle { - val in = Input(Bool()) - val out = Output(Bool()) - }) - - object State extends ChiselEnum { - val sNone, sOne1, sTwo1s = Value - } - - val state = RegInit(State.sNone) - - io.out := (state === State.sTwo1s) - - switch(state) { - is(State.sNone) { - when(io.in) { - state := State.sOne1 - } - } - is(State.sOne1) { - when(io.in) { - state := State.sTwo1s - }.otherwise { - state := State.sNone - } - } - is(State.sTwo1s) { - when(!io.in) { - state := State.sNone - } - } - } -} - -class DetectTwoOnesTester extends CookbookTester(10) { - - val dut = Module(new DetectTwoOnes) - - // Inputs and expected results - val inputs: Vec[Bool] = VecInit(false.B, true.B, false.B, true.B, true.B, true.B, false.B, true.B, true.B, false.B) - val expected: Vec[Bool] = - VecInit(false.B, false.B, false.B, false.B, false.B, true.B, true.B, false.B, false.B, true.B) - - dut.io.in := inputs(cycle) - assert(dut.io.out === expected(cycle)) -} - -class FSMSpec extends CookbookSpec { - "DetectTwoOnes" should "work" in { - assertTesterPasses { new DetectTwoOnesTester } - } -} diff --git a/src/test/scala/cookbook/RegOfVec.scala b/src/test/scala/cookbook/RegOfVec.scala deleted file mode 100644 index ddb615c7..00000000 --- a/src/test/scala/cookbook/RegOfVec.scala +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package cookbook - -import chisel3._ - -/* ### How do I create a Reg of type Vec? - * - * For information, please see the API documentation for Vec - * (https://chisel.eecs.berkeley.edu/api/index.html#chisel3.Vec) - */ -class RegOfVec extends CookbookTester(2) { - // Reg of Vec of 32-bit UInts without initialization - val regOfVec = Reg(Vec(4, UInt(32.W))) - regOfVec(0) := 123.U // a couple of assignments - regOfVec(2) := regOfVec(0) - - // Reg of Vec of 32-bit UInts initialized to zero - // Note that Seq.fill constructs 4 32-bit UInt literals with the value 0 - // Vec(...) then constructs a Wire of these literals - // The Reg is then initialized to the value of the Wire (which gives it the same type) - val initRegOfVec = RegInit(VecInit(Seq.fill(4)(0.U(32.W)))) - - // Simple test (cycle comes from superclass) - when(cycle === 2.U) { assert(regOfVec(2) === 123.U) } - for (elt <- initRegOfVec) { assert(elt === 0.U) } -} - -class RegOfVecSpec extends CookbookSpec { - "RegOfVec" should "work" in { - assertTesterPasses { new RegOfVec } - } -} diff --git a/src/test/scala/cookbook/UInt2Bundle.scala b/src/test/scala/cookbook/UInt2Bundle.scala deleted file mode 100644 index f5180c90..00000000 --- a/src/test/scala/cookbook/UInt2Bundle.scala +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package cookbook - -import chisel3._ - -/* ### How do I create a Bundle from a UInt? - * - * On an instance of the Bundle, call the method fromBits with the UInt as the argument - */ -class UInt2Bundle extends CookbookTester(1) { - // Example - class MyBundle extends Bundle { - val foo = UInt(4.W) - val bar = UInt(4.W) - } - val uint = 0xb4.U - val bundle = uint.asTypeOf(new MyBundle) - printf(p"$bundle") // Bundle(foo -> 11, bar -> 4) - - // Test - assert(bundle.foo === 0xb.U) - assert(bundle.bar === 0x4.U) -} - -class UInt2BundleSpec extends CookbookSpec { - "UInt2Bundle" should "work" in { - assertTesterPasses { new UInt2Bundle } - } -} diff --git a/src/test/scala/cookbook/UInt2VecOfBool.scala b/src/test/scala/cookbook/UInt2VecOfBool.scala deleted file mode 100644 index 9aaf63e9..00000000 --- a/src/test/scala/cookbook/UInt2VecOfBool.scala +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package cookbook - -import chisel3._ - -/* ### How do I create a Vec of Bools from a UInt? - * - * Use the builtin function [[chisel3.Bits.asBools]] to create a Scala Seq of Bool, - * then wrap the resulting Seq in Vec(...) - */ -class UInt2VecOfBool extends CookbookTester(1) { - // Example - val uint = 0xc.U - val vec = VecInit(uint.asBools) - printf(p"$vec") // Vec(0, 0, 1, 1) - - // Test - assert(vec(0) === false.B) - assert(vec(1) === false.B) - assert(vec(2) === true.B) - assert(vec(3) === true.B) -} - -class UInt2VecOfBoolSpec extends CookbookSpec { - "UInt2VecOfBool" should "work" in { - assertTesterPasses { new UInt2VecOfBool } - } -} diff --git a/src/test/scala/cookbook/VecOfBool2UInt.scala b/src/test/scala/cookbook/VecOfBool2UInt.scala deleted file mode 100644 index ca1413dc..00000000 --- a/src/test/scala/cookbook/VecOfBool2UInt.scala +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package cookbook - -import chisel3._ - -/* ### How do I create a UInt from a Vec of Bool? - * - * Use the builtin function asUInt - */ -class VecOfBool2UInt extends CookbookTester(1) { - // Example - val vec = VecInit(true.B, false.B, true.B, true.B) - val uint = vec.asUInt - printf(p"$uint") // 13 - - /* Test - * - * (remember leftmost Bool in Vec is low order bit) - */ - assert(0xd.U === uint) -} - -class VecOfBool2UIntSpec extends CookbookSpec { - "VecOfBool2UInt" should "work" in { - assertTesterPasses { new VecOfBool2UInt } - } -} diff --git a/src/test/scala/examples/ImplicitStateVendingMachine.scala b/src/test/scala/examples/ImplicitStateVendingMachine.scala deleted file mode 100644 index 36ac82ab..00000000 --- a/src/test/scala/examples/ImplicitStateVendingMachine.scala +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package examples - -import chiselTests.ChiselFlatSpec -import chisel3._ - -// Vending machine implemented with an implicit state machine -class ImplicitStateVendingMachine extends SimpleVendingMachine { - // We let the value of nickel be 1 and dime be 2 for efficiency reasons - val value = RegInit(0.asUInt(3.W)) - val incValue = WireDefault(0.asUInt(3.W)) - val doDispense = value >= 4.U // 4 * nickel as 1 == $0.20 - - when(doDispense) { - value := 0.U // No change given - }.otherwise { - value := value + incValue - } - - when(io.nickel) { incValue := 1.U } - when(io.dime) { incValue := 2.U } - - io.dispense := doDispense -} - -class ImplicitStateVendingMachineSpec extends ChiselFlatSpec { - "An vending machine implemented with implicit state" should "work" in { - assertTesterPasses { new SimpleVendingMachineTester(new ImplicitStateVendingMachine) } - } -} diff --git a/src/test/scala/examples/SimpleVendingMachine.scala b/src/test/scala/examples/SimpleVendingMachine.scala deleted file mode 100644 index 819669a3..00000000 --- a/src/test/scala/examples/SimpleVendingMachine.scala +++ /dev/null @@ -1,98 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package examples - -import chiselTests.ChiselFlatSpec -import chisel3.testers.{BasicTester, TesterDriver} -import chisel3._ -import chisel3.util._ - -class SimpleVendingMachineIO extends Bundle { - val nickel = Input(Bool()) - val dime = Input(Bool()) - val dispense = Output(Bool()) -} - -// Superclass for vending machines with very simple IO -abstract class SimpleVendingMachine extends Module { - val io = IO(new SimpleVendingMachineIO) - assert(!(io.nickel && io.dime), "Only one of nickel or dime can be input at a time!") -} - -// Vending machine implemented with a Finite State Machine -class FSMVendingMachine extends SimpleVendingMachine { - val sIdle :: s5 :: s10 :: s15 :: sOk :: Nil = Enum(5) - val state = RegInit(sIdle) - - switch(state) { - is(sIdle) { - when(io.nickel) { state := s5 } - when(io.dime) { state := s10 } - } - is(s5) { - when(io.nickel) { state := s10 } - when(io.dime) { state := s15 } - } - is(s10) { - when(io.nickel) { state := s15 } - when(io.dime) { state := sOk } - } - is(s15) { - when(io.nickel) { state := sOk } - when(io.dime) { state := sOk } - } - is(sOk) { - state := sIdle - } - } - io.dispense := (state === sOk) -} - -class VerilogVendingMachine extends BlackBox { - // Because this is a blackbox, we must explicitly add clock and reset - val io = IO(new SimpleVendingMachineIO { - val clock = Input(Clock()) - val reset = Input(Reset()) - }) -} - -// Shim because Blackbox io is slightly different than normal Chisel Modules -class VerilogVendingMachineWrapper extends SimpleVendingMachine { - val impl = Module(new VerilogVendingMachine) - impl.io.clock := clock - impl.io.reset := reset - impl.io.nickel := io.nickel - impl.io.dime := io.dime - io.dispense := impl.io.dispense -} - -// Accept a reference to a SimpleVendingMachine so it can be constructed inside -// the tester (in a call to Module.apply as required by Chisel -class SimpleVendingMachineTester(mod: => SimpleVendingMachine) extends BasicTester { - - val dut = Module(mod) - - val (cycle, done) = Counter(true.B, 10) - when(done) { stop(); stop() } // Stop twice because of Verilator - - val nickelInputs = VecInit(true.B, true.B, true.B, true.B, true.B, false.B, false.B, false.B, true.B, false.B) - val dimeInputs = VecInit(false.B, false.B, false.B, false.B, false.B, true.B, true.B, false.B, false.B, true.B) - val expected = VecInit(false.B, false.B, false.B, false.B, true.B, false.B, false.B, true.B, false.B, false.B) - - dut.io.nickel := nickelInputs(cycle) - dut.io.dime := dimeInputs(cycle) - assert(dut.io.dispense === expected(cycle)) -} - -class SimpleVendingMachineSpec extends ChiselFlatSpec { - "An FSM implementation of a vending machine" should "work" in { - assertTesterPasses { new SimpleVendingMachineTester(new FSMVendingMachine) } - } - "An Verilog implementation of a vending machine" should "work" in { - assertTesterPasses( - new SimpleVendingMachineTester(new VerilogVendingMachineWrapper), - List("/chisel3/VerilogVendingMachine.v"), - annotations = TesterDriver.verilatorOnly - ) - } -} diff --git a/src/test/scala/examples/VendingMachineGenerator.scala b/src/test/scala/examples/VendingMachineGenerator.scala deleted file mode 100644 index 4adae987..00000000 --- a/src/test/scala/examples/VendingMachineGenerator.scala +++ /dev/null @@ -1,130 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package examples - -import chiselTests.ChiselFlatSpec -import chisel3.testers.BasicTester -import chisel3._ -import chisel3.util._ - -import VendingMachineUtils._ - -class VendingMachineIO(val legalCoins: Seq[Coin]) extends Bundle { - require(legalCoins.size >= 1, "The vending machine must accept at least 1 coin!") - // Order of coins by value - val coins: Seq[Coin] = legalCoins.sortBy(_.value) - // Map of coin names to their relative position in value (ie. index in inputs) - val indexMap: Map[String, Int] = coins.map(_.name).zipWithIndex.toMap - - require( - coins.map(_.value % coins.head.value == 0).reduce(_ && _), - "All coins must be a multiple of the lowest value coin!" - ) - - val inputs = Input(Vec(legalCoins.size, Bool())) - val dispense = Output(Bool()) - - def apply(coin: String): Unit = { - val idx = indexMap(coin) - inputs(idx) := true.B - } -} - -// Superclass for parameterized vending machines -abstract class ParameterizedVendingMachine(legalCoins: Seq[Coin], val sodaCost: Int) extends Module { - val io = IO(new VendingMachineIO(legalCoins)) - // Enforce one hot - if (io.inputs.size > 1) { - for (input <- io.inputs) { - when(input) { - assert(io.inputs.filterNot(_ == input).map(!_).reduce(_ && _), "Only 1 coin can be input in a given cycle!") - } - } - } -} - -class VendingMachineGenerator( - legalCoins: Seq[Coin], - sodaCost: Int) - extends ParameterizedVendingMachine(legalCoins, sodaCost) { - require(sodaCost > 0, "Sodas must actually cost something!") - - // All coin values are normalized to a multiple of the minimum coin value - val minCoin = io.coins.head.value - val maxCoin = io.coins.last.value - val maxValue = (sodaCost + maxCoin - minCoin) / minCoin // normalize to minimum value - - val width = log2Ceil(maxValue + 1).W - val value = RegInit(0.asUInt(width)) - val incValue = WireDefault(0.asUInt(width)) - val doDispense = value >= (sodaCost / minCoin).U - - when(doDispense) { - value := 0.U // No change given - }.otherwise { - value := value + incValue - } - - for ((coin, index) <- io.coins.zipWithIndex) { - when(io.inputs(index)) { incValue := (coin.value / minCoin).U } - } - io.dispense := doDispense -} - -class ParameterizedVendingMachineTester( - mod: => ParameterizedVendingMachine, - testLength: Int) - extends BasicTester { - require(testLength > 0, "Test length must be positive!") - - // Construct the module - val dut = Module(mod) - val coins = dut.io.coins - - // Inputs and expected results - // Do random testing - private val _rand = scala.util.Random - val inputs: Seq[Option[Coin]] = Seq.fill(testLength)(coins.lift(_rand.nextInt(coins.size + 1))) - val expected: Seq[Boolean] = getExpectedResults(inputs, dut.sodaCost) - - val inputVec: Vec[UInt] = VecInit(inputs.map { - case Some(coin) => (1 << dut.io.indexMap(coin.name)).asUInt(coins.size.W) - case None => 0.asUInt(coins.size.W) - }) - val expectedVec: Vec[Bool] = VecInit(expected.map(_.B)) - - val (idx, done) = Counter(true.B, testLength + 1) - when(done) { stop(); stop() } // Two stops for Verilator - - dut.io.inputs := inputVec(idx).asBools - assert(dut.io.dispense === expectedVec(idx)) -} - -class VendingMachineGeneratorSpec extends ChiselFlatSpec { - behavior.of("The vending machine generator") - - it should "generate a vending machine that accepts only nickels and dimes and costs $0.20" in { - val coins = Seq(Nickel, Dime) - assertTesterPasses { - new ParameterizedVendingMachineTester(new VendingMachineGenerator(coins, 20), 100) - } - } - it should "generate a vending machine that only accepts one kind of coin" in { - val coins = Seq(Nickel) - assertTesterPasses { - new ParameterizedVendingMachineTester(new VendingMachineGenerator(coins, 30), 100) - } - } - it should "generate a more realistic vending machine that costs $1.50" in { - val coins = Seq(Penny, Nickel, Dime, Quarter) - assertTesterPasses { - new ParameterizedVendingMachineTester(new VendingMachineGenerator(coins, 150), 100) - } - } - it should "generate a Harry Potter themed vending machine" in { - val coins = Seq(Knut, Sickle) // Galleons are worth too much - assertTesterPasses { - new ParameterizedVendingMachineTester(new VendingMachineGenerator(coins, Galleon.value), 100) - } - } -} diff --git a/src/test/scala/examples/VendingMachineUtils.scala b/src/test/scala/examples/VendingMachineUtils.scala deleted file mode 100644 index 8d5aea57..00000000 --- a/src/test/scala/examples/VendingMachineUtils.scala +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package examples - -import scala.collection.mutable - -/* Useful utilities for testing vending machines */ -object VendingMachineUtils { - abstract class Coin(val name: String, val value: Int) - // US Coins - case object Penny extends Coin("penny", 1) - case object Nickel extends Coin("nickel", 5) - case object Dime extends Coin("dime", 10) - case object Quarter extends Coin("quarter", 25) - - // Harry Potter Coins - case object Knut extends Coin("knut", Penny.value * 2) // Assuming 1 Knut is worth $0.02 - case object Sickle extends Coin("sickle", Knut.value * 29) - case object Galleon extends Coin("galleon", Sickle.value * 17) - - def getExpectedResults(inputs: Seq[Option[Coin]], sodaCost: Int): Seq[Boolean] = { - var value = 0 - val outputs = mutable.ArrayBuffer.empty[Boolean] - for (input <- inputs) { - val incValue = input match { - case Some(coin) => coin.value - case None => 0 - } - if (value >= sodaCost) { - outputs.append(true) - value = 0 - } else { - outputs.append(false) - value += incValue - } - } - outputs.toSeq - } -} |
