diff options
| author | Jack | 2022-01-12 04:27:19 +0000 |
|---|---|---|
| committer | Jack | 2022-01-12 04:27:19 +0000 |
| commit | 29df513e348cc809876893f650af8180f0190496 (patch) | |
| tree | 06daaea954b4e5af7113f06e4bdbb78b33515cb3 /core/src/main/scala/chisel3/internal | |
| parent | 5242ce90659decb9058ee75db56e5c188029fbf9 (diff) | |
| parent | 747d16311bdf185d2e98e452b14cb5d8ccca004c (diff) | |
Merge branch 'master' into 3.5-release
Diffstat (limited to 'core/src/main/scala/chisel3/internal')
| -rw-r--r-- | core/src/main/scala/chisel3/internal/BiConnect.scala | 154 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/internal/Binding.scala | 48 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/internal/Builder.scala | 220 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/internal/Error.scala | 108 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/internal/MonoConnect.scala | 152 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/internal/Namer.scala | 24 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/internal/SourceInfo.scala | 1 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/internal/firrtl/Converter.scala | 189 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/internal/firrtl/IR.scala | 262 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/internal/prefix.scala | 4 |
10 files changed, 671 insertions, 491 deletions
diff --git a/core/src/main/scala/chisel3/internal/BiConnect.scala b/core/src/main/scala/chisel3/internal/BiConnect.scala index aa58cb95..5b4ad1b9 100644 --- a/core/src/main/scala/chisel3/internal/BiConnect.scala +++ b/core/src/main/scala/chisel3/internal/BiConnect.scala @@ -4,7 +4,7 @@ package chisel3.internal import chisel3._ import chisel3.experimental.dataview.reify -import chisel3.experimental.{Analog, BaseModule, attach} +import chisel3.experimental.{attach, Analog, BaseModule} import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl.{Connect, DefInvalid} @@ -14,18 +14,17 @@ import chisel3.internal.sourceinfo._ import scala.annotation.tailrec /** -* BiConnect.connect executes a bidirectional connection element-wise. -* -* Note that the arguments are left and right (not source and sink) so the -* intent is for the operation to be commutative. -* -* The connect operation will recurse down the left Data (with the right Data). -* An exception will be thrown if a movement through the left cannot be matched -* in the right (or if the right side has extra fields). -* -* See elemConnect for details on how the root connections are issued. -* -*/ + * BiConnect.connect executes a bidirectional connection element-wise. + * + * Note that the arguments are left and right (not source and sink) so the + * intent is for the operation to be commutative. + * + * The connect operation will recurse down the left Data (with the right Data). + * An exception will be thrown if a movement through the left cannot be matched + * in the right (or if the right side has extra fields). + * + * See elemConnect for details on how the root connections are issued. + */ private[chisel3] object BiConnect { // These are all the possible exceptions that can be thrown. @@ -53,26 +52,32 @@ private[chisel3] object BiConnect { BiConnectException(": DontCare cannot be a connection sink (LHS)") /** This function is what recursively tries to connect a left and right together - * - * There is some cleverness in the use of internal try-catch to catch exceptions - * during the recursive decent and then rethrow them with extra information added. - * This gives the user a 'path' to where in the connections things went wrong. - */ - def connect(sourceInfo: SourceInfo, connectCompileOptions: CompileOptions, left: Data, right: Data, context_mod: RawModule): Unit = { + * + * There is some cleverness in the use of internal try-catch to catch exceptions + * during the recursive decent and then rethrow them with extra information added. + * This gives the user a 'path' to where in the connections things went wrong. + */ + def connect( + sourceInfo: SourceInfo, + connectCompileOptions: CompileOptions, + left: Data, + right: Data, + context_mod: RawModule + ): Unit = { (left, right) match { // Handle element case (root case) case (left_a: Analog, right_a: Analog) => try { markAnalogConnected(sourceInfo, left_a, context_mod) markAnalogConnected(sourceInfo, right_a, context_mod) - } catch { // convert attach exceptions to BiConnectExceptions + } catch { // convert attach exceptions to BiConnectExceptions case attach.AttachException(message) => throw BiConnectException(message) } attach.impl(Seq(left_a, right_a), context_mod)(sourceInfo) case (left_a: Analog, DontCare) => try { markAnalogConnected(sourceInfo, left_a, context_mod) - } catch { // convert attach exceptions to BiConnectExceptions + } catch { // convert attach exceptions to BiConnectExceptions case attach.AttachException(message) => throw BiConnectException(message) } pushCommand(DefInvalid(sourceInfo, left_a.lref)) @@ -82,7 +87,7 @@ private[chisel3] object BiConnect { // TODO(twigg): Verify the element-level classes are connectable } // Handle Vec case - case (left_v: Vec[Data@unchecked], right_v: Vec[Data@unchecked]) => { + case (left_v: Vec[Data @unchecked], right_v: Vec[Data @unchecked]) => { if (left_v.length != right_v.length) { throw MismatchedVecException } @@ -96,7 +101,7 @@ private[chisel3] object BiConnect { } } // Handle Vec connected to DontCare - case (left_v: Vec[Data@unchecked], DontCare) => { + case (left_v: Vec[Data @unchecked], DontCare) => { for (idx <- 0 until left_v.length) { try { implicit val compileOptions = connectCompileOptions @@ -107,7 +112,7 @@ private[chisel3] object BiConnect { } } // Handle DontCare connected to Vec - case (DontCare, right_v: Vec[Data@unchecked]) => { + case (DontCare, right_v: Vec[Data @unchecked]) => { for (idx <- 0 until right_v.length) { try { implicit val compileOptions = connectCompileOptions @@ -135,7 +140,7 @@ private[chisel3] object BiConnect { case _ => true } } - def canBeSink(data: Data): Boolean = traceFlow(true, data) + def canBeSink(data: Data): Boolean = traceFlow(true, data) def canBeSource(data: Data): Boolean = traceFlow(false, data) // chisel3 <> is commutative but FIRRTL <- is not val flipConnection = !canBeSink(left_r) || !canBeSource(right_r) @@ -181,21 +186,23 @@ private[chisel3] object BiConnect { } // Do connection of two Records - def recordConnect(sourceInfo: SourceInfo, - connectCompileOptions: CompileOptions, - left_r: Record, - right_r: Record, - context_mod: RawModule): Unit = { + def recordConnect( + sourceInfo: SourceInfo, + connectCompileOptions: CompileOptions, + left_r: Record, + right_r: Record, + context_mod: RawModule + ): Unit = { // Verify right has no extra fields that left doesn't have - for((field, right_sub) <- right_r.elements) { - if(!left_r.elements.isDefinedAt(field)) { + for ((field, right_sub) <- right_r.elements) { + if (!left_r.elements.isDefinedAt(field)) { if (connectCompileOptions.connectFieldsMustMatch) { throw MissingLeftFieldException(field) } } } // For each field in left, descend with right - for((field, left_sub) <- left_r.elements) { + for ((field, left_sub) <- left_r.elements) { try { right_r.elements.get(field) match { case Some(right_sub) => connect(sourceInfo, connectCompileOptions, left_sub, right_sub, context_mod) @@ -211,7 +218,6 @@ private[chisel3] object BiConnect { } } - // These functions (finally) issue the connection operation // Issue with right as sink, left as source private def issueConnectL2R(left: Element, right: Element)(implicit sourceInfo: SourceInfo): Unit = { @@ -238,13 +244,19 @@ private[chisel3] object BiConnect { // This function checks if element-level connection operation allowed. // Then it either issues it or throws the appropriate exception. - def elemConnect(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions, _left: Element, _right: Element, context_mod: RawModule): Unit = { - import BindingDirection.{Internal, Input, Output} // Using extensively so import these + def elemConnect( + implicit sourceInfo: SourceInfo, + connectCompileOptions: CompileOptions, + _left: Element, + _right: Element, + context_mod: RawModule + ): Unit = { + import BindingDirection.{Input, Internal, Output} // Using extensively so import these val left = reify(_left) val right = reify(_right) // If left or right have no location, assume in context module // This can occur if one of them is a literal, unbound will error previously - val left_mod: BaseModule = left.topBinding.location.getOrElse(context_mod) + val left_mod: BaseModule = left.topBinding.location.getOrElse(context_mod) val right_mod: BaseModule = right.topBinding.location.getOrElse(context_mod) val left_parent = Builder.retrieveParent(left_mod, context_mod).getOrElse(None) @@ -254,54 +266,54 @@ private[chisel3] object BiConnect { val right_direction = BindingDirection.from(right.topBinding, right.direction) // CASE: Context is same module as left node and right node is in a child module - if((left_mod == context_mod) && (right_parent == context_mod)) { + if ((left_mod == context_mod) && (right_parent == context_mod)) { // Thus, right node better be a port node and thus have a direction hint ((left_direction, right_direction): @unchecked) match { // CURRENT MOD CHILD MOD - case (Input, Input) => issueConnectL2R(left, right) - case (Internal, Input) => issueConnectL2R(left, right) + case (Input, Input) => issueConnectL2R(left, right) + case (Internal, Input) => issueConnectL2R(left, right) - case (Output, Output) => issueConnectR2L(left, right) - case (Internal, Output) => issueConnectR2L(left, right) + case (Output, Output) => issueConnectR2L(left, right) + case (Internal, Output) => issueConnectR2L(left, right) - case (Input, Output) => throw BothDriversException - case (Output, Input) => throw NeitherDriverException - case (_, Internal) => throw UnknownRelationException + case (Input, Output) => throw BothDriversException + case (Output, Input) => throw NeitherDriverException + case (_, Internal) => throw UnknownRelationException } } // CASE: Context is same module as right node and left node is in child module - else if((right_mod == context_mod) && (left_parent == context_mod)) { + else if ((right_mod == context_mod) && (left_parent == context_mod)) { // Thus, left node better be a port node and thus have a direction hint ((left_direction, right_direction): @unchecked) match { // CHILD MOD CURRENT MOD - case (Input, Input) => issueConnectR2L(left, right) - case (Input, Internal) => issueConnectR2L(left, right) + case (Input, Input) => issueConnectR2L(left, right) + case (Input, Internal) => issueConnectR2L(left, right) - case (Output, Output) => issueConnectL2R(left, right) - case (Output, Internal) => issueConnectL2R(left, right) + case (Output, Output) => issueConnectL2R(left, right) + case (Output, Internal) => issueConnectL2R(left, right) - case (Input, Output) => throw NeitherDriverException - case (Output, Input) => throw BothDriversException - case (Internal, _) => throw UnknownRelationException + case (Input, Output) => throw NeitherDriverException + case (Output, Input) => throw BothDriversException + case (Internal, _) => throw UnknownRelationException } } // CASE: Context is same module that both left node and right node are in - else if( (context_mod == left_mod) && (context_mod == right_mod) ) { + else if ((context_mod == left_mod) && (context_mod == right_mod)) { ((left_direction, right_direction): @unchecked) match { // CURRENT MOD CURRENT MOD - case (Input, Output) => issueConnectL2R(left, right) - case (Input, Internal) => issueConnectL2R(left, right) - case (Internal, Output) => issueConnectL2R(left, right) + case (Input, Output) => issueConnectL2R(left, right) + case (Input, Internal) => issueConnectL2R(left, right) + case (Internal, Output) => issueConnectL2R(left, right) - case (Output, Input) => issueConnectR2L(left, right) - case (Output, Internal) => issueConnectR2L(left, right) - case (Internal, Input) => issueConnectR2L(left, right) + case (Output, Input) => issueConnectR2L(left, right) + case (Output, Internal) => issueConnectR2L(left, right) + case (Internal, Input) => issueConnectR2L(left, right) - case (Input, Input) => throw BothDriversException - case (Output, Output) => throw BothDriversException - case (Internal, Internal) => { + case (Input, Input) => throw BothDriversException + case (Output, Output) => throw BothDriversException + case (Internal, Internal) => { if (connectCompileOptions.dontAssumeDirectionality) { throw UnknownDriverException } else { @@ -314,22 +326,22 @@ private[chisel3] object BiConnect { // CASE: Context is the parent module of both the module containing left node // and the module containing right node // Note: This includes case when left and right in same module but in parent - else if((left_parent == context_mod) && (right_parent == context_mod)) { + else if ((left_parent == context_mod) && (right_parent == context_mod)) { // Thus both nodes must be ports and have a direction hint ((left_direction, right_direction): @unchecked) match { // CHILD MOD CHILD MOD - case (Input, Output) => issueConnectR2L(left, right) - case (Output, Input) => issueConnectL2R(left, right) + case (Input, Output) => issueConnectR2L(left, right) + case (Output, Input) => issueConnectL2R(left, right) - case (Input, Input) => throw NeitherDriverException - case (Output, Output) => throw BothDriversException - case (_, Internal) => + case (Input, Input) => throw NeitherDriverException + case (Output, Output) => throw BothDriversException + case (_, Internal) => if (connectCompileOptions.dontAssumeDirectionality) { throw UnknownRelationException } else { issueConnectR2L(left, right) } - case (Internal, _) => + case (Internal, _) => if (connectCompileOptions.dontAssumeDirectionality) { throw UnknownRelationException } else { @@ -347,7 +359,7 @@ private[chisel3] object BiConnect { def markAnalogConnected(implicit sourceInfo: SourceInfo, analog: Analog, contextModule: RawModule): Unit = { analog.biConnectLocs.get(contextModule) match { case Some(sl) => throw AttachAlreadyBulkConnectedException(sl) - case None => // Do nothing + case None => // Do nothing } // Mark bulk connected analog.biConnectLocs(contextModule) = sourceInfo diff --git a/core/src/main/scala/chisel3/internal/Binding.scala b/core/src/main/scala/chisel3/internal/Binding.scala index a0dcc20c..6431dd23 100644 --- a/core/src/main/scala/chisel3/internal/Binding.scala +++ b/core/src/main/scala/chisel3/internal/Binding.scala @@ -12,14 +12,16 @@ import scala.collection.immutable.VectorMap */ object requireIsHardware { def apply(node: Data, msg: String = ""): Unit = { - node._parent match { // Compatibility layer hack + node._parent match { // Compatibility layer hack case Some(x: BaseModule) => x._compatAutoWrapPorts case _ => } if (!node.isSynthesizable) { val prefix = if (msg.nonEmpty) s"$msg " else "" - throw ExpectedHardwareException(s"$prefix'$node' must be hardware, " + - "not a bare Chisel type. Perhaps you forgot to wrap it in Wire(_) or IO(_)?") + throw ExpectedHardwareException( + s"$prefix'$node' must be hardware, " + + "not a bare Chisel type. Perhaps you forgot to wrap it in Wire(_) or IO(_)?" + ) } } } @@ -36,12 +38,15 @@ object requireIsChiselType { // Element only direction used for the Binding system only. private[chisel3] sealed abstract class BindingDirection private[chisel3] object BindingDirection { + /** Internal type or wire */ case object Internal extends BindingDirection + /** Module port with output direction */ case object Output extends BindingDirection + /** Module port with input direction */ case object Input extends BindingDirection @@ -50,11 +55,12 @@ private[chisel3] object BindingDirection { */ def from(binding: TopBinding, direction: ActualDirection): BindingDirection = { binding match { - case PortBinding(_) => direction match { - case ActualDirection.Output => Output - case ActualDirection.Input => Input - case dir => throw new RuntimeException(s"Unexpected port element direction '$dir'") - } + case PortBinding(_) => + direction match { + case ActualDirection.Output => Output + case ActualDirection.Input => Input + case dir => throw new RuntimeException(s"Unexpected port element direction '$dir'") + } case _ => Internal } } @@ -81,7 +87,7 @@ sealed trait ConstrainedBinding extends TopBinding { // This allows aspect modules to pretend to be enclosed modules for connectivity checking, // inside vs outside instance checking, etc. Builder.aspectModule(enclosure) match { - case None => Some(enclosure) + case None => Some(enclosure) case Some(aspect) => Some(aspect) } } @@ -100,18 +106,29 @@ sealed trait ConditionalDeclarable extends TopBinding { case class PortBinding(enclosure: BaseModule) extends ConstrainedBinding -case class OpBinding(enclosure: RawModule, visibility: Option[WhenContext]) extends ConstrainedBinding with ReadOnlyBinding with ConditionalDeclarable -case class MemoryPortBinding(enclosure: RawModule, visibility: Option[WhenContext]) extends ConstrainedBinding with ConditionalDeclarable -case class RegBinding(enclosure: RawModule, visibility: Option[WhenContext]) extends ConstrainedBinding with ConditionalDeclarable -case class WireBinding(enclosure: RawModule, visibility: Option[WhenContext]) extends ConstrainedBinding with ConditionalDeclarable +case class OpBinding(enclosure: RawModule, visibility: Option[WhenContext]) + extends ConstrainedBinding + with ReadOnlyBinding + with ConditionalDeclarable +case class MemoryPortBinding(enclosure: RawModule, visibility: Option[WhenContext]) + extends ConstrainedBinding + with ConditionalDeclarable +case class RegBinding(enclosure: RawModule, visibility: Option[WhenContext]) + extends ConstrainedBinding + with ConditionalDeclarable +case class WireBinding(enclosure: RawModule, visibility: Option[WhenContext]) + extends ConstrainedBinding + with ConditionalDeclarable case class ChildBinding(parent: Data) extends Binding { def location: Option[BaseModule] = parent.topBinding.location } + /** Special binding for Vec.sample_element */ case class SampleElementBinding[T <: Data](parent: Vec[T]) extends Binding { def location = parent.topBinding.location } + /** Special binding for Mem types */ case class MemTypeBinding[T <: Data](parent: MemBase[T]) extends Binding { def location: Option[BaseModule] = parent._parent @@ -122,12 +139,13 @@ case class DontCareBinding() extends UnconstrainedBinding // Views currently only support 1:1 Element-level mappings private[chisel3] case class ViewBinding(target: Element) extends UnconstrainedBinding + /** Binding for Aggregate Views * @param childMap Mapping from children of this view to each child's target * @param target Optional Data this Aggregate views if the view is total and the target is a Data */ -private[chisel3] case class AggregateViewBinding(childMap: Map[Data, Element], target: Option[Data]) extends UnconstrainedBinding - +private[chisel3] case class AggregateViewBinding(childMap: Map[Data, Element], target: Option[Data]) + extends UnconstrainedBinding /** Binding for Data's returned from accessing an Instance/Definition members, if not readable/writable port */ private[chisel3] case object CrossModuleBinding extends TopBinding { diff --git a/core/src/main/scala/chisel3/internal/Builder.scala b/core/src/main/scala/chisel3/internal/Builder.scala index 71894887..fb6ebcc7 100644 --- a/core/src/main/scala/chisel3/internal/Builder.scala +++ b/core/src/main/scala/chisel3/internal/Builder.scala @@ -6,7 +6,7 @@ import scala.util.DynamicVariable import scala.collection.mutable.ArrayBuffer import chisel3._ import chisel3.experimental._ -import chisel3.experimental.hierarchy.{Instance, Clone} +import chisel3.experimental.hierarchy.{Clone, Instance} import chisel3.internal.firrtl._ import chisel3.internal.naming._ import _root_.firrtl.annotations.{CircuitName, ComponentName, IsMember, ModuleName, Named, ReferenceTarget} @@ -34,8 +34,8 @@ private[chisel3] class Namespace(keywords: Set[String]) { private def sanitize(s: String, leadingDigitOk: Boolean = false): String = { // TODO what character set does FIRRTL truly support? using ANSI C for now def legalStart(c: Char) = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' - def legal(c: Char) = legalStart(c) || (c >= '0' && c <= '9') - val res = s filter legal + def legal(c: Char) = legalStart(c) || (c >= '0' && c <= '9') + val res = s.filter(legal) val headOk = (!res.isEmpty) && (leadingDigitOk || legalStart(res.head)) if (headOk) res else s"_$res" } @@ -55,6 +55,7 @@ private[chisel3] class Namespace(keywords: Set[String]) { } private[chisel3] object Namespace { + /** Constructs an empty Namespace */ def empty: Namespace = new Namespace(Set.empty[String]) } @@ -73,14 +74,17 @@ private[chisel3] class IdGen { * These are only valid once the design has been elaborated, and should not be used during its construction. */ trait InstanceId { - def instanceName: String - def pathName: String + def instanceName: String + def pathName: String def parentPathName: String - def parentModName: String + def parentModName: String + /** Returns a FIRRTL Named that refers to this object in the elaborated hardware graph */ def toNamed: Named + /** Returns a FIRRTL IsMember that refers to this object in the elaborated hardware graph */ def toTarget: IsMember + /** Returns a FIRRTL IsMember that refers to the absolute path to this object in the elaborated hardware graph */ def toAbsoluteTarget: IsMember } @@ -111,10 +115,10 @@ private[chisel3] trait HasId extends InstanceId { private var prefix_seed: Prefix = Nil // Post-seed hooks called to carry the suggested seeds to other candidates as needed - private val suggest_postseed_hooks = scala.collection.mutable.ListBuffer.empty[String=>Unit] + private val suggest_postseed_hooks = scala.collection.mutable.ListBuffer.empty[String => Unit] // Post-seed hooks called to carry the auto seeds to other candidates as needed - private val auto_postseed_hooks = scala.collection.mutable.ListBuffer.empty[String=>Unit] + private val auto_postseed_hooks = scala.collection.mutable.ListBuffer.empty[String => Unit] /** Takes the last seed suggested. Multiple calls to this function will take the last given seed, unless * this HasId is a module port (see overridden method in Data.scala). @@ -124,7 +128,7 @@ private[chisel3] trait HasId extends InstanceId { * * Is a lower priority than [[suggestName]], in that regardless of whether [[autoSeed]] * was called, [[suggestName]] will always take precedence if it was called. - * + * * @param seed Seed for the name of this component * @return this object */ @@ -132,7 +136,7 @@ private[chisel3] trait HasId extends InstanceId { // Bypass the overridden behavior of autoSeed in [[Data]], apply autoSeed even to ports private[chisel3] def forceAutoSeed(seed: String): this.type = { auto_seed = Some(seed) - for(hook <- auto_postseed_hooks) { hook(seed) } + for (hook <- auto_postseed_hooks) { hook(seed) } prefix_seed = Builder.getPrefix this } @@ -143,14 +147,14 @@ private[chisel3] trait HasId extends InstanceId { * * Is a higher priority than [[autoSeed]], in that regardless of whether [[autoSeed]] * was called, [[suggestName]] will always take precedence. - * + * * @param seed The seed for the name of this component * @return this object */ - def suggestName(seed: =>String): this.type = { - if(suggested_seed.isEmpty) suggested_seed = Some(seed) + def suggestName(seed: => String): this.type = { + if (suggested_seed.isEmpty) suggested_seed = Some(seed) prefix_seed = Builder.getPrefix - for(hook <- suggest_postseed_hooks) { hook(seed) } + for (hook <- suggest_postseed_hooks) { hook(seed) } this } @@ -171,6 +175,7 @@ private[chisel3] trait HasId extends InstanceId { * @return the name, if it can be computed */ private[chisel3] def _computeName(defaultPrefix: Option[String], defaultSeed: Option[String]): Option[String] = { + /** Computes a name of this signal, given the seed and prefix * @param seed * @param prefix @@ -189,14 +194,14 @@ private[chisel3] trait HasId extends InstanceId { defaultSeed.map { default => defaultPrefix match { case Some(p) => buildName(default, p :: construction_prefix.reverse) - case None => buildName(default, construction_prefix.reverse) + case None => buildName(default, construction_prefix.reverse) } } } } /** This resolves the precedence of [[autoSeed]] and [[suggestName]] - * + * * @return the current calculation of a name, if it exists */ private[chisel3] def seedOpt: Option[String] = suggested_seed.orElse(auto_seed) @@ -206,14 +211,14 @@ private[chisel3] trait HasId extends InstanceId { private[chisel3] def hasAutoSeed: Boolean = auto_seed.isDefined - private[chisel3] def addSuggestPostnameHook(hook: String=>Unit): Unit = suggest_postseed_hooks += hook - private[chisel3] def addAutoPostnameHook(hook: String=>Unit): Unit = auto_postseed_hooks += hook + private[chisel3] def addSuggestPostnameHook(hook: String => Unit): Unit = suggest_postseed_hooks += hook + private[chisel3] def addAutoPostnameHook(hook: String => Unit): Unit = auto_postseed_hooks += hook // Uses a namespace to convert suggestion into a true name // Will not do any naming if the reference already assigned. // (e.g. tried to suggest a name to part of a Record) - private[chisel3] def forceName(prefix: Option[String], default: =>String, namespace: Namespace): Unit = - if(_ref.isEmpty) { + private[chisel3] def forceName(prefix: Option[String], default: => String, namespace: Namespace): Unit = + if (_ref.isEmpty) { val candidate_name = _computeName(prefix, Some(default)).get val available_name = namespace.name(candidate_name) setRef(Ref(available_name)) @@ -226,15 +231,15 @@ private[chisel3] trait HasId extends InstanceId { _ref = Some(imm) } } - private[chisel3] def setRef(parent: HasId, name: String): Unit = setRef(Slot(Node(parent), name)) - private[chisel3] def setRef(parent: HasId, index: Int): Unit = setRef(Index(Node(parent), ILit(index))) - private[chisel3] def setRef(parent: HasId, index: UInt): Unit = setRef(Index(Node(parent), index.ref)) - private[chisel3] def getRef: Arg = _ref.get + private[chisel3] def setRef(parent: HasId, name: String): Unit = setRef(Slot(Node(parent), name)) + private[chisel3] def setRef(parent: HasId, index: Int): Unit = setRef(Index(Node(parent), ILit(index))) + private[chisel3] def setRef(parent: HasId, index: UInt): Unit = setRef(Index(Node(parent), index.ref)) + private[chisel3] def getRef: Arg = _ref.get private[chisel3] def getOptionRef: Option[Arg] = _ref private def refName(c: Component): String = _ref match { - case Some(arg) => arg fullName c - case None => _computeName(None, None).get + case Some(arg) => arg.fullName(c) + case None => _computeName(None, None).get } // Helper for reifying views if they map to a single Target @@ -253,33 +258,35 @@ private[chisel3] trait HasId extends InstanceId { (p._component, this) match { case (Some(c), _) => refName(c) case (None, d: Data) if d.topBindingOpt == Some(CrossModuleBinding) => _ref.get.localName - case (None, _) => throwException(s"signalName/pathName should be called after circuit elaboration: $this, ${_parent}") + case (None, _) => + throwException(s"signalName/pathName should be called after circuit elaboration: $this, ${_parent}") } case None => throwException("this cannot happen") } def pathName: String = _parent match { - case None => instanceName + case None => instanceName case Some(ViewParent) => s"${reifyParent.pathName}.$instanceName" - case Some(p) => s"${p.pathName}.$instanceName" + case Some(p) => s"${p.pathName}.$instanceName" } def parentPathName: String = _parent match { case Some(ViewParent) => reifyParent.pathName - case Some(p) => p.pathName - case None => throwException(s"$instanceName doesn't have a parent") + case Some(p) => p.pathName + case None => throwException(s"$instanceName doesn't have a parent") } def parentModName: String = _parent match { case Some(ViewParent) => reifyParent.name - case Some(p) => p.name - case None => throwException(s"$instanceName doesn't have a parent") + case Some(p) => p.name + case None => throwException(s"$instanceName doesn't have a parent") } // TODO Should this be public? protected def circuitName: String = _parent match { - case None => _circuit match { - case None => instanceName - case Some(o) => o.circuitName - } + case None => + _circuit match { + case None => instanceName + case Some(o) => o.circuitName + } case Some(ViewParent) => reifyParent.circuitName - case Some(p) => p.circuitName + case Some(p) => p.circuitName } private[chisel3] def getPublicFields(rootClass: Class[_]): Seq[java.lang.reflect.Method] = { @@ -302,8 +309,10 @@ private[chisel3] trait HasId extends InstanceId { this.getClass.getMethods.filter(isPublicVal).sortWith(_.getName < _.getName) } } + /** Holds the implementation of toNamed for Data and MemBase */ private[chisel3] trait NamedComponent extends HasId { + /** Returns a FIRRTL ComponentName that references this object * @note Should not be called until circuit elaboration is complete */ @@ -319,7 +328,7 @@ private[chisel3] trait NamedComponent extends HasId { import _root_.firrtl.annotations.{Target, TargetToken} val root = _parent.map { case ViewParent => reifyParent - case other => other + case other => other }.get.getTarget // All NamedComponents will have a parent, only the top module can have None here Target.toTargetTokens(name).toList match { case TargetToken.Ref(r) :: components => root.ref(r).copy(component = components) @@ -333,8 +342,8 @@ private[chisel3] trait NamedComponent extends HasId { def makeTarget(p: BaseModule) = p.toAbsoluteTarget.ref(localTarget.ref).copy(component = localTarget.component) _parent match { case Some(ViewParent) => makeTarget(reifyParent) - case Some(parent) => makeTarget(parent) - case None => localTarget + case Some(parent) => makeTarget(parent) + case None => localTarget } } } @@ -369,9 +378,9 @@ private[chisel3] class DynamicContext(val annotationSeq: AnnotationSeq) { // Set by object Module.apply before calling class Module constructor // Used to distinguish between no Module() wrapping, multiple wrappings, and rewrapping var readyForModuleConstr: Boolean = false - var whenStack: List[WhenContext] = Nil - var currentClock: Option[Clock] = None - var currentReset: Option[Reset] = None + var whenStack: List[WhenContext] = Nil + var currentClock: Option[Clock] = None + var currentReset: Option[Reset] = None val errors = new ErrorLog val namingStack = new NamingStack // Used to indicate if this is the top-level module of full elaboration, or from a Definition @@ -396,7 +405,7 @@ private[chisel3] object Builder extends LazyLogging { def restoreContext(dc: DynamicContext) = dynamicContextVar.value = Some(dc) // Ensure we have a thread-specific ChiselContext - private val chiselContext = new ThreadLocal[ChiselContext]{ + private val chiselContext = new ThreadLocal[ChiselContext] { override def initialValue: ChiselContext = { new ChiselContext } @@ -419,12 +428,12 @@ private[chisel3] object Builder extends LazyLogging { def idGen: IdGen = chiselContext.get.idGen def globalNamespace: Namespace = dynamicContext.globalNamespace - def components: ArrayBuffer[Component] = dynamicContext.components - def annotations: ArrayBuffer[ChiselAnnotation] = dynamicContext.annotations - def annotationSeq: AnnotationSeq = dynamicContext.annotationSeq - def namingStack: NamingStack = dynamicContext.namingStack + def components: ArrayBuffer[Component] = dynamicContext.components + def annotations: ArrayBuffer[ChiselAnnotation] = dynamicContext.annotations + def annotationSeq: AnnotationSeq = dynamicContext.annotationSeq + def namingStack: NamingStack = dynamicContext.namingStack - def unnamedViews: ArrayBuffer[Data] = dynamicContext.unnamedViews + def unnamedViews: ArrayBuffer[Data] = dynamicContext.unnamedViews def viewNamespace: Namespace = chiselContext.get.viewNamespace // Puts a prefix string onto the prefix stack @@ -441,8 +450,8 @@ private[chisel3] object Builder extends LazyLogging { def pushPrefix(d: HasId): Boolean = { def buildAggName(id: HasId): Option[String] = { def getSubName(field: Data): Option[String] = field.getOptionRef.flatMap { - case Slot(_, field) => Some(field) // Record - case Index(_, ILit(n)) => Some(n.toString) // Vec static indexing + case Slot(_, field) => Some(field) // Record + case Index(_, ILit(n)) => Some(n.toString) // Vec static indexing case Index(_, ULit(n, _)) => Some(n.toString) // Vec lit indexing case Index(_, _: Node) => None // Vec dynamic indexing case ModuleIO(_, n) => Some(n) // BlackBox port @@ -452,13 +461,14 @@ private[chisel3] object Builder extends LazyLogging { // If the binding is None, this is an illegal connection and later logic will error def recData(data: Data): Option[String] = data.binding.flatMap { case (_: WireBinding | _: RegBinding | _: MemoryPortBinding | _: OpBinding) => data.seedOpt - case ChildBinding(parent) => recData(parent).map { p => - // And name of the field if we have one, we don't for dynamic indexing of Vecs - getSubName(data).map(p + "_" + _).getOrElse(p) - } - case SampleElementBinding(parent) => recData(parent) + case ChildBinding(parent) => + recData(parent).map { p => + // And name of the field if we have one, we don't for dynamic indexing of Vecs + getSubName(data).map(p + "_" + _).getOrElse(p) + } + case SampleElementBinding(parent) => recData(parent) case PortBinding(mod) if Builder.currentModule.contains(mod) => data.seedOpt - case PortBinding(mod) => map2(mod.seedOpt, data.seedOpt)(_ + "_" + _) + case PortBinding(mod) => map2(mod.seedOpt, data.seedOpt)(_ + "_" + _) case (_: LitBinding | _: DontCareBinding) => None case _ => Some("view_") // TODO implement } @@ -495,30 +505,31 @@ private[chisel3] object Builder extends LazyLogging { def currentModule: Option[BaseModule] = dynamicContextVar.value match { case Some(dyanmicContext) => dynamicContext.currentModule - case _ => None + case _ => None } def currentModule_=(target: Option[BaseModule]): Unit = { dynamicContext.currentModule = target } def aspectModule(module: BaseModule): Option[BaseModule] = dynamicContextVar.value match { case Some(dynamicContext) => dynamicContext.aspectModule.get(module) - case _ => None + case _ => None } + /** Retrieves the parent of a module based on the elaboration context - * - * @param module the module to get the parent of - * @param context the context the parent should be evaluated in - * @return the parent of the module provided - */ + * + * @param module the module to get the parent of + * @param context the context the parent should be evaluated in + * @return the parent of the module provided + */ def retrieveParent(module: BaseModule, context: BaseModule): Option[BaseModule] = { module._parent match { case Some(parentModule) => { //if a parent exists investigate, otherwise return None context match { case aspect: ModuleAspect => { //if aspect context, do the translation - Builder.aspectModule(parentModule) match { - case Some(parentAspect) => Some(parentAspect) //we've found a translation - case _ => Some(parentModule) //no translation found - } + Builder.aspectModule(parentModule) match { + case Some(parentAspect) => Some(parentAspect) //we've found a translation + case _ => Some(parentModule) //no translation found + } } //otherwise just return our parent case _ => Some(parentModule) } @@ -531,10 +542,11 @@ private[chisel3] object Builder extends LazyLogging { } def forcedModule: BaseModule = currentModule match { case Some(module) => module - case None => throwException( - "Error: Not in a Module. Likely cause: Missed Module() wrap or bare chisel API call." - // A bare api call is, e.g. calling Wire() from the scala console). - ) + case None => + throwException( + "Error: Not in a Module. Likely cause: Missed Module() wrap or bare chisel API call." + // A bare api call is, e.g. calling Wire() from the scala console). + ) } def referenceUserModule: RawModule = { currentModule match { @@ -543,18 +555,20 @@ private[chisel3] object Builder extends LazyLogging { case Some(aspect: RawModule) => aspect case other => module } - case _ => throwException( - "Error: Not in a RawModule. Likely cause: Missed Module() wrap, bare chisel API call, or attempting to construct hardware inside a BlackBox." - // A bare api call is, e.g. calling Wire() from the scala console). - ) + case _ => + throwException( + "Error: Not in a RawModule. Likely cause: Missed Module() wrap, bare chisel API call, or attempting to construct hardware inside a BlackBox." + // A bare api call is, e.g. calling Wire() from the scala console). + ) } } def forcedUserModule: RawModule = currentModule match { case Some(module: RawModule) => module - case _ => throwException( - "Error: Not in a UserModule. Likely cause: Missed Module() wrap, bare chisel API call, or attempting to construct hardware inside a BlackBox." - // A bare api call is, e.g. calling Wire() from the scala console). - ) + case _ => + throwException( + "Error: Not in a UserModule. Likely cause: Missed Module() wrap, bare chisel API call, or attempting to construct hardware inside a BlackBox." + // A bare api call is, e.g. calling Wire() from the scala console). + ) } def hasDynamicContext: Boolean = dynamicContextVar.value.isDefined @@ -594,8 +608,8 @@ private[chisel3] object Builder extends LazyLogging { def inDefinition: Boolean = { dynamicContextVar.value - .map(_.inDefinition) - .getOrElse(false) + .map(_.inDefinition) + .getOrElse(false) } def forcedClock: Clock = currentClock.getOrElse( @@ -623,10 +637,11 @@ private[chisel3] object Builder extends LazyLogging { * (Note: Map is Iterable[Tuple2[_,_]] and thus excluded) */ def nameRecursively(prefix: String, nameMe: Any, namer: (HasId, String) => Unit): Unit = nameMe match { - case (id: Instance[_]) => id.underlying match { - case Clone(m: internal.BaseModule.ModuleClone[_]) => namer(m.getPorts, prefix) - case _ => - } + case (id: Instance[_]) => + id.underlying match { + case Clone(m: internal.BaseModule.ModuleClone[_]) => namer(m.getPorts, prefix) + case _ => + } case (id: HasId) => namer(id, prefix) case Some(elt) => nameRecursively(prefix, elt, namer) case (iter: Iterable[_]) if iter.hasDefiniteSize => @@ -644,7 +659,7 @@ private[chisel3] object Builder extends LazyLogging { throwException(m) } } - def warning(m: => String): Unit = if (dynamicContextVar.value.isDefined) errors.warning(m) + def warning(m: => String): Unit = if (dynamicContextVar.value.isDefined) errors.warning(m) def deprecated(m: => String, location: Option[String] = None): Unit = if (dynamicContextVar.value.isDefined) errors.deprecated(m, location) @@ -667,7 +682,7 @@ private[chisel3] object Builder extends LazyLogging { if (getScalaMajorVersion == 11) { val url = _root_.firrtl.stage.transforms.CheckScalaVersion.migrationDocumentLink val msg = s"Chisel 3.4 is the last version that will support Scala 2.11. " + - s"Please upgrade to Scala 2.12. See $url" + s"Please upgrade to Scala 2.12. See $url" deprecated(msg, Some("")) } } @@ -680,8 +695,7 @@ private[chisel3] object Builder extends LazyLogging { for (view <- unnamedViews) { val localTarget = view.toTarget val absTarget = view.toAbsoluteTarget - val elts = getRecursiveFields.lazily(view, "") - .collect { case (elt: Element, _) => elt } + val elts = getRecursiveFields.lazily(view, "").collect { case (elt: Element, _) => elt } for (elt <- elts) { val targetOfView = reify(elt) renames.record(localTarget, targetOfView.toTarget) @@ -691,10 +705,14 @@ private[chisel3] object Builder extends LazyLogging { renames } - private[chisel3] def build[T <: BaseModule](f: => T, dynamicContext: DynamicContext, forceModName: Boolean = true): (Circuit, T) = { + private[chisel3] def build[T <: BaseModule]( + f: => T, + dynamicContext: DynamicContext, + forceModName: Boolean = true + ): (Circuit, T) = { dynamicContextVar.withValue(Some(dynamicContext)) { ViewParent // Must initialize the singleton in a Builder context or weird things can happen - // in tiny designs/testcases that never access anything in chisel3.internal + // in tiny designs/testcases that never access anything in chisel3.internal checkScalaVersion() logger.info("Elaborating design...") val mod = f @@ -719,24 +737,28 @@ object DynamicNamingStack { def pushContext(): NamingContextInterface = { Builder.namingStackOption match { case Some(namingStack) => namingStack.pushContext() - case None => DummyNamer + case None => DummyNamer } } def popReturnContext[T <: Any](prefixRef: T, until: NamingContextInterface): T = { until match { case DummyNamer => - require(Builder.namingStackOption.isEmpty, - "Builder context must remain stable throughout a chiselName-annotated function invocation") + require( + Builder.namingStackOption.isEmpty, + "Builder context must remain stable throughout a chiselName-annotated function invocation" + ) case context: NamingContext => - require(Builder.namingStackOption.isDefined, - "Builder context must remain stable throughout a chiselName-annotated function invocation") + require( + Builder.namingStackOption.isDefined, + "Builder context must remain stable throughout a chiselName-annotated function invocation" + ) Builder.namingStackOption.get.popContext(prefixRef, context) } prefixRef } - def length() : Int = Builder.namingStackOption.get.length + def length(): Int = Builder.namingStackOption.get.length } /** Casts BigInt to Int, issuing an error when the input isn't representable. */ diff --git a/core/src/main/scala/chisel3/internal/Error.scala b/core/src/main/scala/chisel3/internal/Error.scala index d6e0c0e6..c42f39ed 100644 --- a/core/src/main/scala/chisel3/internal/Error.scala +++ b/core/src/main/scala/chisel3/internal/Error.scala @@ -38,7 +38,7 @@ object ExceptionHelpers { */ def trimStackTraceToUserCode( packageTrimlist: Set[String] = packageTrimlist, - anchor: Option[String] = Some(builderName) + anchor: Option[String] = Some(builderName) ): Unit = { def inTrimlist(ste: StackTraceElement) = { val packageName = ste.getClassName().takeWhile(_ != '.') @@ -47,25 +47,28 @@ object ExceptionHelpers { // Step 1: Remove elements from the top in the package trimlist ((a: Array[StackTraceElement]) => a.dropWhile(inTrimlist)) - // Step 2: Optionally remove elements from the bottom until the anchor + // Step 2: Optionally remove elements from the bottom until the anchor .andThen(_.reverse) - .andThen( a => + .andThen(a => anchor match { case Some(b) => a.dropWhile(ste => !ste.getClassName.startsWith(b)) case None => a } ) - // Step 3: Remove elements from the bottom in the package trimlist + // Step 3: Remove elements from the bottom in the package trimlist .andThen(_.dropWhile(inTrimlist)) - // Step 4: Reverse back to the original order + // Step 4: Reverse back to the original order .andThen(_.reverse.toArray) - // Step 5: Add ellipsis stack trace elements and "--full-stacktrace" info + // Step 5: Add ellipsis stack trace elements and "--full-stacktrace" info .andThen(a => ellipsis() +: a :+ ellipsis() :+ - ellipsis(Some("Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace"))) - // Step 5: Mutate the stack trace in this exception + ellipsis( + Some("Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace") + ) + ) + // Step 5: Mutate the stack trace in this exception .andThen(throwable.setStackTrace(_)) .apply(throwable.getStackTrace) } @@ -95,18 +98,21 @@ class ChiselException(message: String, cause: Throwable = null) extends Exceptio case a => getCauses(a, throwable +: acc) } - /** Returns true if an exception contains */ + /** Returns true if an exception contains */ private def containsBuilder(throwable: Throwable): Boolean = - throwable.getStackTrace().collectFirst { - case ste if ste.getClassName().startsWith(ExceptionHelpers.builderName) => throwable - }.isDefined + throwable + .getStackTrace() + .collectFirst { + case ste if ste.getClassName().startsWith(ExceptionHelpers.builderName) => throwable + } + .isDefined /** Examine this [[ChiselException]] and it's causes for the first [[Throwable]] that contains a stack trace including * a stack trace element whose declaring class is the [[builderName]]. If no such element exists, return this * [[ChiselException]]. */ private lazy val likelyCause: Throwable = - getCauses(this).collectFirst{ case a if containsBuilder(a) => a }.getOrElse(this) + getCauses(this).collectFirst { case a if containsBuilder(a) => a }.getOrElse(this) /** For an exception, return a stack trace trimmed to user code only * @@ -139,7 +145,9 @@ class ChiselException(message: String, cause: Throwable = null) extends Exceptio sw.write(likelyCause.toString + "\n") sw.write("\t...\n") trimmed.foreach(ste => sw.write(s"\tat $ste\n")) - sw.write("\t... (Stack trace trimmed to user code only, rerun with --full-stacktrace if you wish to see the full stack trace)\n") + sw.write( + "\t... (Stack trace trimmed to user code only, rerun with --full-stacktrace if you wish to see the full stack trace)\n" + ) sw.toString } } @@ -157,6 +165,7 @@ private[chisel3] object ErrorLog { } private[chisel3] class ErrorLog { + /** Log an error message */ def error(m: => String): Unit = errors += new Error(m, getUserLineNumber) @@ -168,16 +177,17 @@ private[chisel3] class ErrorLog { /** Emit an informational message */ @deprecated("This method will be removed in 3.5", "3.4") def info(m: String): Unit = - println(new Info("[%2.3f] %s".format(elapsedTime/1e3, m), None)) + println(new Info("[%2.3f] %s".format(elapsedTime / 1e3, m), None)) /** Log a deprecation warning message */ def deprecated(m: => String, location: Option[String]): Unit = { val sourceLoc = location match { case Some(loc) => loc - case None => getUserLineNumber match { - case Some(elt: StackTraceElement) => s"${elt.getFileName}:${elt.getLineNumber}" - case None => "(unknown)" - } + case None => + getUserLineNumber match { + case Some(elt: StackTraceElement) => s"${elt.getFileName}:${elt.getLineNumber}" + case None => "(unknown)" + } } val thisEntry = (m, sourceLoc) @@ -186,15 +196,20 @@ private[chisel3] class ErrorLog { /** Throw an exception if any errors have yet occurred. */ def checkpoint(logger: Logger): Unit = { - deprecations.foreach { case ((message, sourceLoc), count) => - logger.warn(s"${ErrorLog.depTag} $sourceLoc ($count calls): $message") + deprecations.foreach { + case ((message, sourceLoc), count) => + logger.warn(s"${ErrorLog.depTag} $sourceLoc ($count calls): $message") } errors.foreach(e => logger.error(e.toString)) if (!deprecations.isEmpty) { - logger.warn(s"${ErrorLog.warnTag} ${Console.YELLOW}There were ${deprecations.size} deprecated function(s) used." + - s" These may stop compiling in a future release - you are encouraged to fix these issues.${Console.RESET}") - logger.warn(s"${ErrorLog.warnTag} Line numbers for deprecations reported by Chisel may be inaccurate; enable scalac compiler deprecation warnings via either of the following methods:") + logger.warn( + s"${ErrorLog.warnTag} ${Console.YELLOW}There were ${deprecations.size} deprecated function(s) used." + + s" These may stop compiling in a future release - you are encouraged to fix these issues.${Console.RESET}" + ) + logger.warn( + s"${ErrorLog.warnTag} Line numbers for deprecations reported by Chisel may be inaccurate; enable scalac compiler deprecation warnings via either of the following methods:" + ) logger.warn(s"${ErrorLog.warnTag} In the sbt interactive console, enter:") logger.warn(s"""${ErrorLog.warnTag} set scalacOptions in ThisBuild ++= Seq("-unchecked", "-deprecation")""") logger.warn(s"${ErrorLog.warnTag} or, in your build.sbt, add the line:") @@ -205,16 +220,22 @@ private[chisel3] class ErrorLog { val allWarnings = errors.filter(!_.isFatal) if (!allWarnings.isEmpty && !allErrors.isEmpty) { - logger.warn(s"${ErrorLog.errTag} There were ${Console.RED}${allErrors.size} error(s)${Console.RESET} and ${Console.YELLOW}${allWarnings.size} warning(s)${Console.RESET} during hardware elaboration.") + logger.warn( + s"${ErrorLog.errTag} There were ${Console.RED}${allErrors.size} error(s)${Console.RESET} and ${Console.YELLOW}${allWarnings.size} warning(s)${Console.RESET} during hardware elaboration." + ) } else if (!allWarnings.isEmpty) { - logger.warn(s"${ErrorLog.warnTag} There were ${Console.YELLOW}${allWarnings.size} warning(s)${Console.RESET} during hardware elaboration.") + logger.warn( + s"${ErrorLog.warnTag} There were ${Console.YELLOW}${allWarnings.size} warning(s)${Console.RESET} during hardware elaboration." + ) } else if (!allErrors.isEmpty) { - logger.warn(s"${ErrorLog.errTag} There were ${Console.RED}${allErrors.size} error(s)${Console.RESET} during hardware elaboration.") + logger.warn( + s"${ErrorLog.errTag} There were ${Console.RED}${allErrors.size} error(s)${Console.RESET} during hardware elaboration." + ) } if (!allErrors.isEmpty) { throw new ChiselException("Fatal errors during hardware elaboration. Look above for error list.") - with scala.util.control.NoStackTrace + with scala.util.control.NoStackTrace } else { // No fatal errors, clear accumulated warnings since they've been reported errors.clear() @@ -228,20 +249,25 @@ private[chisel3] class ErrorLog { // List of classpath prefixes that are Chisel internals and should be ignored when looking for user code // utils are not part of internals and errors there can be reported val chiselPrefixes = Set( - "java.", - "scala.", - "chisel3.", - "chisel3.internal.", - "chisel3.experimental.", - "chisel3.package$" // for some compatibility / deprecated types - ) + "java.", + "scala.", + "chisel3.", + "chisel3.internal.", + "chisel3.experimental.", + "chisel3.package$" // for some compatibility / deprecated types + ) !chiselPrefixes.filter(className.startsWith(_)).isEmpty } - Thread.currentThread().getStackTrace.toList.dropWhile( - // Get rid of everything in Chisel core - ste => isChiselClassname(ste.getClassName) - ).headOption + Thread + .currentThread() + .getStackTrace + .toList + .dropWhile( + // Get rid of everything in Chisel core + ste => isChiselClassname(ste.getClassName) + ) + .headOption } private val errors = ArrayBuffer[LogEntry]() @@ -257,7 +283,7 @@ private abstract class LogEntry(msg: => String, line: Option[StackTraceElement]) override def toString: String = line match { case Some(l) => s"${format} ${l.getFileName}:${l.getLineNumber}: ${msg} in class ${l.getClassName}" - case None => s"${format} ${msg}" + case None => s"${format} ${msg}" } protected def tag(name: String, color: String): String = @@ -266,7 +292,7 @@ private abstract class LogEntry(msg: => String, line: Option[StackTraceElement]) private class Error(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) { override def isFatal: Boolean = true - def format: String = tag("error", Console.RED) + def format: String = tag("error", Console.RED) } private class Warning(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) { diff --git a/core/src/main/scala/chisel3/internal/MonoConnect.scala b/core/src/main/scala/chisel3/internal/MonoConnect.scala index 6173fc91..b4d9aeff 100644 --- a/core/src/main/scala/chisel3/internal/MonoConnect.scala +++ b/core/src/main/scala/chisel3/internal/MonoConnect.scala @@ -12,28 +12,28 @@ import scala.language.experimental.macros import chisel3.internal.sourceinfo.SourceInfo /** -* MonoConnect.connect executes a mono-directional connection element-wise. -* -* Note that this isn't commutative. There is an explicit source and sink -* already determined before this function is called. -* -* The connect operation will recurse down the left Data (with the right Data). -* An exception will be thrown if a movement through the left cannot be matched -* in the right. The right side is allowed to have extra Record fields. -* Vecs must still be exactly the same size. -* -* See elemConnect for details on how the root connections are issued. -* -* Note that a valid sink must be writable so, one of these must hold: -* - Is an internal writable node (Reg or Wire) -* - Is an output of the current module -* - Is an input of a submodule of the current module -* -* Note that a valid source must be readable so, one of these must hold: -* - Is an internal readable node (Reg, Wire, Op) -* - Is a literal -* - Is a port of the current module or submodule of the current module -*/ + * MonoConnect.connect executes a mono-directional connection element-wise. + * + * Note that this isn't commutative. There is an explicit source and sink + * already determined before this function is called. + * + * The connect operation will recurse down the left Data (with the right Data). + * An exception will be thrown if a movement through the left cannot be matched + * in the right. The right side is allowed to have extra Record fields. + * Vecs must still be exactly the same size. + * + * See elemConnect for details on how the root connections are issued. + * + * Note that a valid sink must be writable so, one of these must hold: + * - Is an internal writable node (Reg or Wire) + * - Is an output of the current module + * - Is an input of a submodule of the current module + * + * Note that a valid source must be readable so, one of these must hold: + * - Is an internal readable node (Reg, Wire, Op) + * - Is a literal + * - Is a port of the current module or submodule of the current module + */ private[chisel3] object MonoConnect { def formatName(data: Data) = s"""${data.earlyName} in ${data.parentNameOpt.getOrElse("(unknown)")}""" @@ -41,9 +41,13 @@ private[chisel3] object MonoConnect { // These are all the possible exceptions that can be thrown. // These are from element-level connection def UnreadableSourceException(sink: Data, source: Data) = - MonoConnectException(s"""${formatName(source)} cannot be read from module ${sink.parentNameOpt.getOrElse("(unknown)")}.""") + MonoConnectException( + s"""${formatName(source)} cannot be read from module ${sink.parentNameOpt.getOrElse("(unknown)")}.""" + ) def UnwritableSinkException(sink: Data, source: Data) = - MonoConnectException(s"""${formatName(sink)} cannot be written from module ${source.parentNameOpt.getOrElse("(unknown)")}.""") + MonoConnectException( + s"""${formatName(sink)} cannot be written from module ${source.parentNameOpt.getOrElse("(unknown)")}.""" + ) def SourceEscapedWhenScopeException(source: Data) = MonoConnectException(s"Source ${formatName(source)} has escaped the scope of the when in which it was constructed.") def SinkEscapedWhenScopeException(sink: Data) = @@ -56,7 +60,9 @@ private[chisel3] object MonoConnect { def MissingFieldException(field: String) = MonoConnectException(s"Source Record missing field ($field).") def MismatchedException(sink: Data, source: Data) = - MonoConnectException(s"Sink (${sink.cloneType.toString}) and Source (${source.cloneType.toString}) have different types.") + MonoConnectException( + s"Sink (${sink.cloneType.toString}) and Source (${source.cloneType.toString}) have different types." + ) def DontCareCantBeSink = MonoConnectException("DontCare cannot be a connection sink") def AnalogCantBeMonoSink(sink: Data) = @@ -64,28 +70,32 @@ private[chisel3] object MonoConnect { def AnalogCantBeMonoSource(source: Data) = MonoConnectException(s"Source ${formatName(source)} of type Analog cannot participate in a mono connection (:=)") def AnalogMonoConnectionException(source: Data, sink: Data) = - MonoConnectException(s"Source ${formatName(source)} and sink ${formatName(sink)} of type Analog cannot participate in a mono connection (:=)") + MonoConnectException( + s"Source ${formatName(source)} and sink ${formatName(sink)} of type Analog cannot participate in a mono connection (:=)" + ) def checkWhenVisibility(x: Data): Boolean = { x.topBinding match { - case mp: MemoryPortBinding => true // TODO (albert-magyar): remove this "bridge" for odd enable logic of current CHIRRTL memories + case mp: MemoryPortBinding => + true // TODO (albert-magyar): remove this "bridge" for odd enable logic of current CHIRRTL memories case cd: ConditionalDeclarable => cd.visibility.map(_.active()).getOrElse(true) case _ => true } } /** This function is what recursively tries to connect a sink and source together - * - * There is some cleverness in the use of internal try-catch to catch exceptions - * during the recursive decent and then rethrow them with extra information added. - * This gives the user a 'path' to where in the connections things went wrong. - */ + * + * There is some cleverness in the use of internal try-catch to catch exceptions + * during the recursive decent and then rethrow them with extra information added. + * This gives the user a 'path' to where in the connections things went wrong. + */ def connect( - sourceInfo: SourceInfo, - connectCompileOptions: CompileOptions, - sink: Data, - source: Data, - context_mod: RawModule): Unit = + sourceInfo: SourceInfo, + connectCompileOptions: CompileOptions, + sink: Data, + source: Data, + context_mod: RawModule + ): Unit = (sink, source) match { // Handle legal element cases, note (Bool, Bool) is caught by the first two, as Bool is a UInt @@ -118,8 +128,8 @@ private[chisel3] object MonoConnect { // Handle Vec case case (sink_v: Vec[Data @unchecked], source_v: Vec[Data @unchecked]) => - if(sink_v.length != source_v.length) { throw MismatchedVecException } - for(idx <- 0 until sink_v.length) { + if (sink_v.length != source_v.length) { throw MismatchedVecException } + for (idx <- 0 until sink_v.length) { try { implicit val compileOptions = connectCompileOptions connect(sourceInfo, connectCompileOptions, sink_v(idx), source_v(idx), context_mod) @@ -129,7 +139,7 @@ private[chisel3] object MonoConnect { } // Handle Vec connected to DontCare. Apply the DontCare to individual elements. case (sink_v: Vec[Data @unchecked], DontCare) => - for(idx <- 0 until sink_v.length) { + for (idx <- 0 until sink_v.length) { try { implicit val compileOptions = connectCompileOptions connect(sourceInfo, connectCompileOptions, sink_v(idx), source, context_mod) @@ -141,7 +151,7 @@ private[chisel3] object MonoConnect { // Handle Record case case (sink_r: Record, source_r: Record) => // For each field, descend with right - for((field, sink_sub) <- sink_r.elements) { + for ((field, sink_sub) <- sink_r.elements) { try { source_r.elements.get(field) match { case Some(source_sub) => connect(sourceInfo, connectCompileOptions, sink_sub, source_sub, context_mod) @@ -158,7 +168,7 @@ private[chisel3] object MonoConnect { // Handle Record connected to DontCare. Apply the DontCare to individual elements. case (sink_r: Record, DontCare) => // For each field, descend with right - for((field, sink_sub) <- sink_r.elements) { + for ((field, sink_sub) <- sink_r.elements) { try { connect(sourceInfo, connectCompileOptions, sink_sub, source, context_mod) } catch { @@ -171,7 +181,7 @@ private[chisel3] object MonoConnect { // DontCare as a sink is illegal. case (DontCare, _) => throw DontCareCantBeSink // Analog is illegal in mono connections. - case (_: Analog, _:Analog) => throw AnalogMonoConnectionException(source, sink) + case (_: Analog, _: Analog) => throw AnalogMonoConnectionException(source, sink) // Analog is illegal in mono connections. case (_: Analog, _) => throw AnalogCantBeMonoSink(sink) // Analog is illegal in mono connections. @@ -192,13 +202,19 @@ private[chisel3] object MonoConnect { // This function checks if element-level connection operation allowed. // Then it either issues it or throws the appropriate exception. - def elemConnect(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions, _sink: Element, _source: Element, context_mod: RawModule): Unit = { - import BindingDirection.{Internal, Input, Output} // Using extensively so import these + def elemConnect( + implicit sourceInfo: SourceInfo, + connectCompileOptions: CompileOptions, + _sink: Element, + _source: Element, + context_mod: RawModule + ): Unit = { + import BindingDirection.{Input, Internal, Output} // Using extensively so import these val sink = reify(_sink) val source = reify(_source) // If source has no location, assume in context module // This can occur if is a literal, unbound will error previously - val sink_mod: BaseModule = sink.topBinding.location.getOrElse(throw UnwritableSinkException(sink, source)) + val sink_mod: BaseModule = sink.topBinding.location.getOrElse(throw UnwritableSinkException(sink, source)) val source_mod: BaseModule = source.topBinding.location.getOrElse(context_mod) val sink_parent = Builder.retrieveParent(sink_mod, context_mod).getOrElse(None) @@ -216,69 +232,69 @@ private[chisel3] object MonoConnect { } // CASE: Context is same module that both left node and right node are in - if( (context_mod == sink_mod) && (context_mod == source_mod) ) { + if ((context_mod == sink_mod) && (context_mod == source_mod)) { ((sink_direction, source_direction): @unchecked) match { // SINK SOURCE // CURRENT MOD CURRENT MOD - case (Output, _) => issueConnect(sink, source) - case (Internal, _) => issueConnect(sink, source) - case (Input, _) => throw UnwritableSinkException(sink, source) + case (Output, _) => issueConnect(sink, source) + case (Internal, _) => issueConnect(sink, source) + case (Input, _) => throw UnwritableSinkException(sink, source) } } // CASE: Context is same module as sink node and right node is in a child module - else if((sink_mod == context_mod) && (source_parent == context_mod)) { + else if ((sink_mod == context_mod) && (source_parent == context_mod)) { // Thus, right node better be a port node and thus have a direction ((sink_direction, source_direction): @unchecked) match { // SINK SOURCE // CURRENT MOD CHILD MOD - case (Internal, Output) => issueConnect(sink, source) - case (Internal, Input) => issueConnect(sink, source) - case (Output, Output) => issueConnect(sink, source) - case (Output, Input) => issueConnect(sink, source) - case (_, Internal) => { + case (Internal, Output) => issueConnect(sink, source) + case (Internal, Input) => issueConnect(sink, source) + case (Output, Output) => issueConnect(sink, source) + case (Output, Input) => issueConnect(sink, source) + case (_, Internal) => { if (!(connectCompileOptions.dontAssumeDirectionality)) { issueConnect(sink, source) } else { throw UnreadableSourceException(sink, source) } } - case (Input, Output) if (!(connectCompileOptions.dontTryConnectionsSwapped)) => issueConnect(source, sink) - case (Input, _) => throw UnwritableSinkException(sink, source) + case (Input, Output) if (!(connectCompileOptions.dontTryConnectionsSwapped)) => issueConnect(source, sink) + case (Input, _) => throw UnwritableSinkException(sink, source) } } // CASE: Context is same module as source node and sink node is in child module - else if((source_mod == context_mod) && (sink_parent == context_mod)) { + else if ((source_mod == context_mod) && (sink_parent == context_mod)) { // Thus, left node better be a port node and thus have a direction ((sink_direction, source_direction): @unchecked) match { // SINK SOURCE // CHILD MOD CURRENT MOD - case (Input, _) => issueConnect(sink, source) - case (Output, _) => throw UnwritableSinkException(sink, source) - case (Internal, _) => throw UnwritableSinkException(sink, source) + case (Input, _) => issueConnect(sink, source) + case (Output, _) => throw UnwritableSinkException(sink, source) + case (Internal, _) => throw UnwritableSinkException(sink, source) } } // CASE: Context is the parent module of both the module containing sink node // and the module containing source node // Note: This includes case when sink and source in same module but in parent - else if((sink_parent == context_mod) && (source_parent == context_mod)) { + else if ((sink_parent == context_mod) && (source_parent == context_mod)) { // Thus both nodes must be ports and have a direction ((sink_direction, source_direction): @unchecked) match { // SINK SOURCE // CHILD MOD CHILD MOD - case (Input, Input) => issueConnect(sink, source) - case (Input, Output) => issueConnect(sink, source) - case (Output, _) => throw UnwritableSinkException(sink, source) - case (_, Internal) => { + case (Input, Input) => issueConnect(sink, source) + case (Input, Output) => issueConnect(sink, source) + case (Output, _) => throw UnwritableSinkException(sink, source) + case (_, Internal) => { if (!(connectCompileOptions.dontAssumeDirectionality)) { issueConnect(sink, source) } else { throw UnreadableSourceException(sink, source) } } - case (Internal, _) => throw UnwritableSinkException(sink, source) + case (Internal, _) => throw UnwritableSinkException(sink, source) } } diff --git a/core/src/main/scala/chisel3/internal/Namer.scala b/core/src/main/scala/chisel3/internal/Namer.scala index c6e36cb6..c36aafef 100644 --- a/core/src/main/scala/chisel3/internal/Namer.scala +++ b/core/src/main/scala/chisel3/internal/Namer.scala @@ -42,6 +42,7 @@ import scala.collection.JavaConverters._ * ability to take descendant naming contexts. */ sealed trait NamingContextInterface { + /** Suggest a name (that will be propagated to FIRRTL) for an object, then returns the object * itself (so this can be inserted transparently anywhere). * Is a no-op (so safe) when applied on objects that aren't named, including non-Chisel data @@ -61,8 +62,7 @@ sealed trait NamingContextInterface { object DummyNamer extends NamingContextInterface { def name[T](obj: T, name: String): T = obj - def namePrefix(prefix: String): Unit = { - } + def namePrefix(prefix: String): Unit = {} } /** Actual namer functionality. @@ -71,7 +71,7 @@ class NamingContext extends NamingContextInterface { val descendants = new IdentityHashMap[AnyRef, ListBuffer[NamingContext]]() val anonymousDescendants = ListBuffer[NamingContext]() val items = ListBuffer[(AnyRef, String)]() - var closed = false // a sanity check to ensure no more name() calls are done after namePrefix + var closed = false // a sanity check to ensure no more name() calls are done after namePrefix /** Adds a NamingContext object as a descendant - where its contained objects will have names * prefixed with the name given to the reference object, if the reference object is named in the @@ -82,11 +82,13 @@ class NamingContext extends NamingContextInterface { case ref: AnyRef => // getOrElseUpdate val l = descendants.get(ref) - val buf = if (l != null) l else { - val value = ListBuffer[NamingContext]() - descendants.put(ref, value) - value - } + val buf = + if (l != null) l + else { + val value = ListBuffer[NamingContext]() + descendants.put(ref, value) + value + } buf += descendant case _ => anonymousDescendants += descendant } @@ -95,8 +97,8 @@ class NamingContext extends NamingContextInterface { def name[T](obj: T, name: String): T = { assert(!closed, "Can't name elements after namePrefix called") obj match { - case _: NoChiselNamePrefix => // Don't name things with NoChiselNamePrefix - case ref: AnyRef => items += ((ref, name)) + case _: NoChiselNamePrefix => // Don't name things with NoChiselNamePrefix + case ref: AnyRef => items += ((ref, name)) case _ => } obj @@ -156,5 +158,5 @@ class NamingStack { } } - def length() : Int = namingStack.length + def length(): Int = namingStack.length } diff --git a/core/src/main/scala/chisel3/internal/SourceInfo.scala b/core/src/main/scala/chisel3/internal/SourceInfo.scala index 0d6d8eb7..dc7f7fab 100644 --- a/core/src/main/scala/chisel3/internal/SourceInfo.scala +++ b/core/src/main/scala/chisel3/internal/SourceInfo.scala @@ -20,6 +20,7 @@ import scala.reflect.macros.blackbox.Context /** Abstract base class for generalized source information. */ sealed trait SourceInfo { + /** A prettier toString * * Make a useful message if SourceInfo is available, nothing otherwise diff --git a/core/src/main/scala/chisel3/internal/firrtl/Converter.scala b/core/src/main/scala/chisel3/internal/firrtl/Converter.scala index ac784882..2d21a7cb 100644 --- a/core/src/main/scala/chisel3/internal/firrtl/Converter.scala +++ b/core/src/main/scala/chisel3/internal/firrtl/Converter.scala @@ -5,7 +5,7 @@ import chisel3._ import chisel3.experimental._ import chisel3.internal.sourceinfo.{NoSourceInfo, SourceInfo, SourceLine, UnlocatableSourceInfo} import firrtl.{ir => fir} -import chisel3.internal.{HasId, castToInt, throwException} +import chisel3.internal.{castToInt, throwException, HasId} import scala.annotation.{nowarn, tailrec} import scala.collection.immutable.Queue @@ -21,9 +21,9 @@ private[chisel3] object Converter { case PString(str) => (str.replaceAll("%", "%%"), List.empty) case format: FirrtlFormat => ("%" + format.specifier, List(format.bits.ref)) - case Name(data) => (data.ref.name, List.empty) + case Name(data) => (data.ref.name, List.empty) case FullName(data) => (data.ref.fullName(ctx), List.empty) - case Percent => ("%%", List.empty) + case Percent => ("%%", List.empty) } private def reportInternalError(msg: String): Nothing = { @@ -53,9 +53,9 @@ private[chisel3] object Converter { def convert(dir: MemPortDirection): firrtl.MPortDir = dir match { case MemPortDirection.INFER => firrtl.MInfer - case MemPortDirection.READ => firrtl.MRead + case MemPortDirection.READ => firrtl.MRead case MemPortDirection.WRITE => firrtl.MWrite - case MemPortDirection.RDWR => firrtl.MReadWrite + case MemPortDirection.RDWR => firrtl.MReadWrite } // TODO @@ -82,7 +82,8 @@ private[chisel3] object Converter { fir.UIntLiteral(n, fir.IntWidth(u.minWidth)) case ULit(n, w) => fir.UIntLiteral(n, convert(w)) - case slit @ SLit(n, w) => fir.SIntLiteral(n, convert(w)) + case slit @ SLit(n, w) => + fir.SIntLiteral(n, convert(w)) val unsigned = if (n < 0) (BigInt(1) << slit.width.get) + n else n val uint = convert(ULit(unsigned, slit.width), ctx, info) fir.DoPrim(firrtl.PrimOps.AsSInt, Seq(uint), Seq.empty, fir.UnknownType) @@ -120,19 +121,43 @@ private[chisel3] object Converter { case e @ DefWire(info, id) => Some(fir.DefWire(convert(info), e.name, extractType(id, info))) case e @ DefReg(info, id, clock) => - Some(fir.DefRegister(convert(info), e.name, extractType(id, info), convert(clock, ctx, info), - firrtl.Utils.zero, convert(getRef(id, info), ctx, info))) + Some( + fir.DefRegister( + convert(info), + e.name, + extractType(id, info), + convert(clock, ctx, info), + firrtl.Utils.zero, + convert(getRef(id, info), ctx, info) + ) + ) case e @ DefRegInit(info, id, clock, reset, init) => - Some(fir.DefRegister(convert(info), e.name, extractType(id, info), convert(clock, ctx, info), - convert(reset, ctx, info), convert(init, ctx, info))) + Some( + fir.DefRegister( + convert(info), + e.name, + extractType(id, info), + convert(clock, ctx, info), + convert(reset, ctx, info), + convert(init, ctx, info) + ) + ) case e @ DefMemory(info, id, t, size) => Some(firrtl.CDefMemory(convert(info), e.name, extractType(t, info), size, false)) case e @ DefSeqMemory(info, id, t, size, ruw) => Some(firrtl.CDefMemory(convert(info), e.name, extractType(t, info), size, true, ruw)) case e: DefMemPort[_] => val info = e.sourceInfo - Some(firrtl.CDefMPort(convert(e.sourceInfo), e.name, fir.UnknownType, - e.source.fullName(ctx), Seq(convert(e.index, ctx, info), convert(e.clock, ctx, info)), convert(e.dir))) + Some( + firrtl.CDefMPort( + convert(e.sourceInfo), + e.name, + fir.UnknownType, + e.source.fullName(ctx), + Seq(convert(e.index, ctx, info), convert(e.clock, ctx, info)), + convert(e.dir) + ) + ) case Connect(info, loc, exp) => Some(fir.Connect(convert(info), convert(loc, ctx, info), convert(exp, ctx, info))) case BulkConnect(info, loc, exp) => @@ -147,16 +172,33 @@ private[chisel3] object Converter { Some(fir.Stop(convert(info), ret, convert(clock, ctx, info), firrtl.Utils.one, e.name)) case e @ Printf(_, info, clock, pable) => val (fmt, args) = unpack(pable, ctx) - Some(fir.Print(convert(info), fir.StringLit(fmt), - args.map(a => convert(a, ctx, info)), convert(clock, ctx, info), firrtl.Utils.one, e.name)) + Some( + fir.Print( + convert(info), + fir.StringLit(fmt), + args.map(a => convert(a, ctx, info)), + convert(clock, ctx, info), + firrtl.Utils.one, + e.name + ) + ) case e @ Verification(_, op, info, clk, pred, msg) => val firOp = op match { case Formal.Assert => fir.Formal.Assert case Formal.Assume => fir.Formal.Assume - case Formal.Cover => fir.Formal.Cover + case Formal.Cover => fir.Formal.Cover } - Some(fir.Verification(firOp, convert(info), convert(clk, ctx, info), - convert(pred, ctx, info), firrtl.Utils.one, fir.StringLit(msg), e.name)) + Some( + fir.Verification( + firOp, + convert(info), + convert(clk, ctx, info), + convert(pred, ctx, info), + firrtl.Utils.one, + fir.StringLit(msg), + e.name + ) + ) case _ => None } @@ -183,59 +225,60 @@ private[chisel3] object Converter { */ def convert(cmds: Seq[Command], ctx: Component): fir.Statement = { @tailrec - def rec(acc: Queue[fir.Statement], - scope: List[WhenFrame]) - (cmds: Seq[Command]): Seq[fir.Statement] = { + def rec(acc: Queue[fir.Statement], scope: List[WhenFrame])(cmds: Seq[Command]): Seq[fir.Statement] = { if (cmds.isEmpty) { assert(scope.isEmpty) acc - } else convertSimpleCommand(cmds.head, ctx) match { - // Most Commands map 1:1 - case Some(stmt) => - rec(acc :+ stmt, scope)(cmds.tail) - // When scoping logic does not map 1:1 and requires pushing/popping WhenFrames - // Please see WhenFrame for more details - case None => cmds.head match { - case WhenBegin(info, pred) => - val when = fir.Conditionally(convert(info), convert(pred, ctx, info), fir.EmptyStmt, fir.EmptyStmt) - val frame = WhenFrame(when, acc, false) - rec(Queue.empty, frame +: scope)(cmds.tail) - case WhenEnd(info, depth, _) => - val frame = scope.head - val when = if (frame.alt) frame.when.copy(alt = fir.Block(acc)) - else frame.when.copy(conseq = fir.Block(acc)) - // Check if this when has an else - cmds.tail.headOption match { - case Some(AltBegin(_)) => - assert(!frame.alt, "Internal Error! Unexpected when structure!") // Only 1 else per when - rec(Queue.empty, frame.copy(when = when, alt = true) +: scope.tail)(cmds.drop(2)) - case _ => // Not followed by otherwise - // If depth > 0 then we need to close multiple When scopes so we add a new WhenEnd - // If we're nested we need to add more WhenEnds to ensure each When scope gets - // properly closed - val cmdsx = if (depth > 0) WhenEnd(info, depth - 1, false) +: cmds.tail else cmds.tail - rec(frame.outer :+ when, scope.tail)(cmdsx) + } else + convertSimpleCommand(cmds.head, ctx) match { + // Most Commands map 1:1 + case Some(stmt) => + rec(acc :+ stmt, scope)(cmds.tail) + // When scoping logic does not map 1:1 and requires pushing/popping WhenFrames + // Please see WhenFrame for more details + case None => + cmds.head match { + case WhenBegin(info, pred) => + val when = fir.Conditionally(convert(info), convert(pred, ctx, info), fir.EmptyStmt, fir.EmptyStmt) + val frame = WhenFrame(when, acc, false) + rec(Queue.empty, frame +: scope)(cmds.tail) + case WhenEnd(info, depth, _) => + val frame = scope.head + val when = + if (frame.alt) frame.when.copy(alt = fir.Block(acc)) + else frame.when.copy(conseq = fir.Block(acc)) + // Check if this when has an else + cmds.tail.headOption match { + case Some(AltBegin(_)) => + assert(!frame.alt, "Internal Error! Unexpected when structure!") // Only 1 else per when + rec(Queue.empty, frame.copy(when = when, alt = true) +: scope.tail)(cmds.drop(2)) + case _ => // Not followed by otherwise + // If depth > 0 then we need to close multiple When scopes so we add a new WhenEnd + // If we're nested we need to add more WhenEnds to ensure each When scope gets + // properly closed + val cmdsx = if (depth > 0) WhenEnd(info, depth - 1, false) +: cmds.tail else cmds.tail + rec(frame.outer :+ when, scope.tail)(cmdsx) + } + case OtherwiseEnd(info, depth) => + val frame = scope.head + val when = frame.when.copy(alt = fir.Block(acc)) + // TODO For some reason depth == 1 indicates the last closing otherwise whereas + // depth == 0 indicates last closing when + val cmdsx = if (depth > 1) OtherwiseEnd(info, depth - 1) +: cmds.tail else cmds.tail + rec(scope.head.outer :+ when, scope.tail)(cmdsx) } - case OtherwiseEnd(info, depth) => - val frame = scope.head - val when = frame.when.copy(alt = fir.Block(acc)) - // TODO For some reason depth == 1 indicates the last closing otherwise whereas - // depth == 0 indicates last closing when - val cmdsx = if (depth > 1) OtherwiseEnd(info, depth - 1) +: cmds.tail else cmds.tail - rec(scope.head.outer :+ when, scope.tail)(cmdsx) } - } } fir.Block(rec(Queue.empty, List.empty)(cmds)) } def convert(width: Width): fir.Width = width match { - case UnknownWidth() => fir.UnknownWidth + case UnknownWidth() => fir.UnknownWidth case KnownWidth(value) => fir.IntWidth(value) } def convert(bp: BinaryPoint): fir.Width = bp match { - case UnknownBinaryPoint => fir.UnknownWidth + case UnknownBinaryPoint => fir.UnknownWidth case KnownBinaryPoint(value) => fir.IntWidth(value) } @@ -248,15 +291,15 @@ private[chisel3] object Converter { def extractType(data: Data, info: SourceInfo): fir.Type = extractType(data, false, info) def extractType(data: Data, clearDir: Boolean, info: SourceInfo): fir.Type = data match { - case _: Clock => fir.ClockType + case _: Clock => fir.ClockType case _: AsyncReset => fir.AsyncResetType - case _: ResetType => fir.ResetType - case d: EnumType => fir.UIntType(convert(d.width)) - case d: UInt => fir.UIntType(convert(d.width)) - case d: SInt => fir.SIntType(convert(d.width)) + case _: ResetType => fir.ResetType + case d: EnumType => fir.UIntType(convert(d.width)) + case d: UInt => fir.UIntType(convert(d.width)) + case d: SInt => fir.SIntType(convert(d.width)) case d: FixedPoint => fir.FixedType(convert(d.width), convert(d.binaryPoint)) - case d: Interval => fir.IntervalType(d.range.lowerBound, d.range.upperBound, d.range.firrtlBinaryPoint) - case d: Analog => fir.AnalogType(convert(d.width)) + case d: Interval => fir.IntervalType(d.range.lowerBound, d.range.upperBound, d.range.firrtlBinaryPoint) + case d: Analog => fir.AnalogType(convert(d.width)) case d: Vec[_] => fir.VectorType(extractType(d.sample_element, clearDir, info), d.length) case d: Record => val childClearDir = clearDir || @@ -269,23 +312,23 @@ private[chisel3] object Converter { fir.Field(getRef(elt, info).name, fir.Flip, extractType(elt, false, info)) } fir.BundleType(d.elements.toIndexedSeq.reverse.map { case (_, e) => eltField(e) }) - } + } def convert(name: String, param: Param): fir.Param = param match { - case IntParam(value) => fir.IntParam(name, value) + case IntParam(value) => fir.IntParam(name, value) case DoubleParam(value) => fir.DoubleParam(name, value) case StringParam(value) => fir.StringParam(name, fir.StringLit(value)) - case RawParam(value) => fir.RawStringParam(name, value) + case RawParam(value) => fir.RawStringParam(name, value) } def convert(port: Port, topDir: SpecifiedDirection = SpecifiedDirection.Unspecified): fir.Port = { val resolvedDir = SpecifiedDirection.fromParent(topDir, port.dir) val dir = resolvedDir match { case SpecifiedDirection.Unspecified | SpecifiedDirection.Output => fir.Output - case SpecifiedDirection.Flip | SpecifiedDirection.Input => fir.Input + case SpecifiedDirection.Flip | SpecifiedDirection.Input => fir.Input } val clearDir = resolvedDir match { - case SpecifiedDirection.Input | SpecifiedDirection.Output => true + case SpecifiedDirection.Input | SpecifiedDirection.Output => true case SpecifiedDirection.Unspecified | SpecifiedDirection.Flip => false } val info = UnlocatableSourceInfo // Unfortunately there is no source locator for ports ATM @@ -297,8 +340,13 @@ private[chisel3] object Converter { case ctx @ DefModule(_, name, ports, cmds) => fir.Module(fir.NoInfo, name, ports.map(p => convert(p)), convert(cmds.toList, ctx)) case ctx @ DefBlackBox(id, name, ports, topDir, params) => - fir.ExtModule(fir.NoInfo, name, ports.map(p => convert(p, topDir)), id.desiredName, - params.map { case (name, p) => convert(name, p) }.toSeq) + fir.ExtModule( + fir.NoInfo, + name, + ports.map(p => convert(p, topDir)), + id.desiredName, + params.map { case (name, p) => convert(name, p) }.toSeq + ) } def convert(circuit: Circuit): fir.Circuit = @@ -310,4 +358,3 @@ private[chisel3] object Converter { fir.Circuit(fir.NoInfo, lazyModules.map(convert), circuit.name) } } - diff --git a/core/src/main/scala/chisel3/internal/firrtl/IR.scala b/core/src/main/scala/chisel3/internal/firrtl/IR.scala index 68f5f18e..1ee8842f 100644 --- a/core/src/main/scala/chisel3/internal/firrtl/IR.scala +++ b/core/src/main/scala/chisel3/internal/firrtl/IR.scala @@ -15,7 +15,6 @@ import scala.collection.immutable.NumericRange import scala.math.BigDecimal.RoundingMode import scala.annotation.nowarn - case class PrimOp(name: String) { override def toString: String = name } @@ -68,35 +67,36 @@ object PrimOp { sealed abstract class Arg { def localName: String = name def contextualName(ctx: Component): String = name - def fullName(ctx: Component): String = contextualName(ctx) + def fullName(ctx: Component): String = contextualName(ctx) def name: String } case class Node(id: HasId) extends Arg { override def contextualName(ctx: Component): String = id.getOptionRef match { case Some(arg) => arg.contextualName(ctx) - case None => id.instanceName + case None => id.instanceName } override def localName: String = id.getOptionRef match { case Some(arg) => arg.localName - case None => id.instanceName + case None => id.instanceName } def name: String = id.getOptionRef match { case Some(arg) => arg.name - case None => id.instanceName + case None => id.instanceName } } object Arg { def earlyLocalName(id: HasId): String = id.getOptionRef match { case Some(Index(Node(imm), Node(value))) => s"${earlyLocalName(imm)}[${earlyLocalName(imm)}]" - case Some(Index(Node(imm), arg)) => s"${earlyLocalName(imm)}[${arg.localName}]" - case Some(Slot(Node(imm), name)) => s"${earlyLocalName(imm)}.$name" - case Some(arg) => arg.name - case None => id match { - case data: Data => data._computeName(None, Some("?")).get - case _ => "?" - } + case Some(Index(Node(imm), arg)) => s"${earlyLocalName(imm)}[${arg.localName}]" + case Some(Slot(Node(imm), name)) => s"${earlyLocalName(imm)}.$name" + case Some(arg) => arg.name + case None => + id match { + case data: Data => data._computeName(None, Some("?")).get + case _ => "?" + } } } @@ -121,8 +121,10 @@ abstract class LitArg(val num: BigInt, widthArg: Width) extends Arg { protected def minWidth: Int if (forcedWidth) { - require(widthArg.get >= minWidth, - s"The literal value ${num} was elaborated with a specified width of ${widthArg.get} bits, but at least ${minWidth} bits are required.") + require( + widthArg.get >= minWidth, + s"The literal value ${num} was elaborated with a specified width of ${widthArg.get} bits, but at least ${minWidth} bits are required." + ) } } @@ -131,8 +133,8 @@ case class ILit(n: BigInt) extends Arg { } case class ULit(n: BigInt, w: Width) extends LitArg(n, w) { - def name: String = "UInt" + width + "(\"h0" + num.toString(16) + "\")" - def minWidth: Int = 1 max n.bitLength + def name: String = "UInt" + width + "(\"h0" + num.toString(16) + "\")" + def minWidth: Int = 1.max(n.bitLength) def cloneWithWidth(newWidth: Width): this.type = { ULit(n, newWidth).asInstanceOf[this.type] @@ -171,8 +173,11 @@ case class IntervalLit(n: BigInt, w: Width, binaryPoint: BinaryPoint) extends Li s"asInterval(${ULit(unsigned, width).name}, ${n}, ${n}, ${binaryPoint.asInstanceOf[KnownBinaryPoint].value})" } val range: IntervalRange = { - new IntervalRange(IntervalRange.getBound(isClosed = true, BigDecimal(n)), - IntervalRange.getBound(isClosed = true, BigDecimal(n)), IntervalRange.getRangeWidth(binaryPoint)) + new IntervalRange( + IntervalRange.getBound(isClosed = true, BigDecimal(n)), + IntervalRange.getBound(isClosed = true, BigDecimal(n)), + IntervalRange.getRangeWidth(binaryPoint) + ) } def minWidth: Int = 1 + n.bitLength @@ -182,6 +187,7 @@ case class IntervalLit(n: BigInt, w: Width, binaryPoint: BinaryPoint) extends Li } case class Ref(name: String) extends Arg + /** Arg for ports of Modules * @param mod the module this port belongs to * @param name the name of the port @@ -190,6 +196,7 @@ case class ModuleIO(mod: BaseModule, name: String) extends Arg { override def contextualName(ctx: Component): String = if (mod eq ctx.id) name else s"${mod.getRef.name}.$name" } + /** Ports of cloned modules (CloneModuleAsRecord) * @param mod The original module for which these ports are a clone * @param name the name of the module instance @@ -224,22 +231,22 @@ object Width { sealed abstract class Width { type W = Int - def min(that: Width): Width = this.op(that, _ min _) - def max(that: Width): Width = this.op(that, _ max _) - def + (that: Width): Width = this.op(that, _ + _) - def + (that: Int): Width = this.op(this, (a, b) => a + that) - def shiftRight(that: Int): Width = this.op(this, (a, b) => 0 max (a - that)) + def min(that: Width): Width = this.op(that, _ min _) + def max(that: Width): Width = this.op(that, _ max _) + def +(that: Width): Width = this.op(that, _ + _) + def +(that: Int): Width = this.op(this, (a, b) => a + that) + def shiftRight(that: Int): Width = this.op(this, (a, b) => 0.max(a - that)) def dynamicShiftLeft(that: Width): Width = this.op(that, (a, b) => a + (1 << b) - 1) def known: Boolean - def get: W + def get: W protected def op(that: Width, f: (W, W) => W): Width } sealed case class UnknownWidth() extends Width { def known: Boolean = false - def get: Int = None.get + def get: Int = None.get def op(that: Width, f: (W, W) => W): Width = this override def toString: String = "" } @@ -247,10 +254,10 @@ sealed case class UnknownWidth() extends Width { sealed case class KnownWidth(value: Int) extends Width { require(value >= 0) def known: Boolean = true - def get: Int = value + def get: Int = value def op(that: Width, f: (W, W) => W): Width = that match { case KnownWidth(x) => KnownWidth(f(value, x)) - case _ => that + case _ => that } override def toString: String = s"<${value.toString}>" } @@ -262,36 +269,35 @@ object BinaryPoint { sealed abstract class BinaryPoint { type W = Int - def max(that: BinaryPoint): BinaryPoint = this.op(that, _ max _) - def + (that: BinaryPoint): BinaryPoint = this.op(that, _ + _) - def + (that: Int): BinaryPoint = this.op(this, (a, b) => a + that) - def shiftRight(that: Int): BinaryPoint = this.op(this, (a, b) => 0 max (a - that)) + def max(that: BinaryPoint): BinaryPoint = this.op(that, _ max _) + def +(that: BinaryPoint): BinaryPoint = this.op(that, _ + _) + def +(that: Int): BinaryPoint = this.op(this, (a, b) => a + that) + def shiftRight(that: Int): BinaryPoint = this.op(this, (a, b) => 0.max(a - that)) def dynamicShiftLeft(that: BinaryPoint): BinaryPoint = this.op(that, (a, b) => a + (1 << b) - 1) def known: Boolean - def get: W + def get: W protected def op(that: BinaryPoint, f: (W, W) => W): BinaryPoint } case object UnknownBinaryPoint extends BinaryPoint { def known: Boolean = false - def get: Int = None.get + def get: Int = None.get def op(that: BinaryPoint, f: (W, W) => W): BinaryPoint = this override def toString: String = "" } sealed case class KnownBinaryPoint(value: Int) extends BinaryPoint { def known: Boolean = true - def get: Int = value + def get: Int = value def op(that: BinaryPoint, f: (W, W) => W): BinaryPoint = that match { case KnownBinaryPoint(x) => KnownBinaryPoint(f(value, x)) - case _ => that + case _ => that } override def toString: String = s"<<${value.toString}>>" } - sealed abstract class MemPortDirection(name: String) { override def toString: String = name } @@ -305,17 +311,18 @@ object MemPortDirection { sealed trait RangeType { def getWidth: Width - def * (that: IntervalRange): IntervalRange - def +& (that: IntervalRange): IntervalRange - def -& (that: IntervalRange): IntervalRange - def << (that: Int): IntervalRange - def >> (that: Int): IntervalRange - def << (that: KnownWidth): IntervalRange - def >> (that: KnownWidth): IntervalRange + def *(that: IntervalRange): IntervalRange + def +&(that: IntervalRange): IntervalRange + def -&(that: IntervalRange): IntervalRange + def <<(that: Int): IntervalRange + def >>(that: Int): IntervalRange + def <<(that: KnownWidth): IntervalRange + def >>(that: KnownWidth): IntervalRange def merge(that: IntervalRange): IntervalRange } object IntervalRange { + /** Creates an IntervalRange, this is used primarily by the range interpolator macro * @param lower lower bound * @param upper upper bound @@ -352,7 +359,9 @@ object IntervalRange { case KnownWidth(w) => val nearestPowerOf2 = BigInt("1" + ("0" * (w - 1)), 2) IntervalRange( - firrtlir.Closed(BigDecimal(-nearestPowerOf2)), firrtlir.Closed(BigDecimal(nearestPowerOf2 - 1)), binaryPoint + firrtlir.Closed(BigDecimal(-nearestPowerOf2)), + firrtlir.Closed(BigDecimal(nearestPowerOf2 - 1)), + binaryPoint ) case _ => IntervalRange(firrtlir.UnknownBound, firrtlir.UnknownBound, binaryPoint) @@ -365,22 +374,19 @@ object IntervalRange { } def getBound(isClosed: Boolean, value: String): firrtlir.Bound = { - if(value == "?") { + if (value == "?") { firrtlir.UnknownBound - } - else if(isClosed) { + } else if (isClosed) { firrtlir.Closed(BigDecimal(value)) - } - else { + } else { firrtlir.Open(BigDecimal(value)) } } def getBound(isClosed: Boolean, value: BigDecimal): firrtlir.Bound = { - if(isClosed) { + if (isClosed) { firrtlir.Closed(value) - } - else { + } else { firrtlir.Open(value) } } @@ -394,33 +400,30 @@ object IntervalRange { } def getBinaryPoint(n: Int): firrtlir.Width = { - if(n < 0) { + if (n < 0) { firrtlir.UnknownWidth - } - else { + } else { firrtlir.IntWidth(n) } } def getBinaryPoint(n: BinaryPoint): firrtlir.Width = { n match { - case UnknownBinaryPoint => firrtlir.UnknownWidth + case UnknownBinaryPoint => firrtlir.UnknownWidth case KnownBinaryPoint(w) => firrtlir.IntWidth(w) } } def getRangeWidth(w: Width): firrtlir.Width = { - if(w.known) { + if (w.known) { firrtlir.IntWidth(w.get) - } - else { + } else { firrtlir.UnknownWidth } } def getRangeWidth(binaryPoint: BinaryPoint): firrtlir.Width = { - if(binaryPoint.known) { + if (binaryPoint.known) { firrtlir.IntWidth(binaryPoint.get) - } - else { + } else { firrtlir.UnknownWidth } } @@ -428,47 +431,46 @@ object IntervalRange { def Unknown: IntervalRange = range"[?,?].?" } - sealed class IntervalRange( - val lowerBound: firrtlir.Bound, - val upperBound: firrtlir.Bound, - private[chisel3] val firrtlBinaryPoint: firrtlir.Width) - extends firrtlir.IntervalType(lowerBound, upperBound, firrtlBinaryPoint) + val lowerBound: firrtlir.Bound, + val upperBound: firrtlir.Bound, + private[chisel3] val firrtlBinaryPoint: firrtlir.Width) + extends firrtlir.IntervalType(lowerBound, upperBound, firrtlBinaryPoint) with RangeType { (lowerBound, upperBound) match { case (firrtlir.Open(begin), firrtlir.Open(end)) => - if(begin >= end) throw new ChiselException(s"Invalid range with ${serialize}") + if (begin >= end) throw new ChiselException(s"Invalid range with ${serialize}") binaryPoint match { case KnownBinaryPoint(bp) => - if(begin >= end - (BigDecimal(1) / BigDecimal(BigInt(1) << bp))) { + if (begin >= end - (BigDecimal(1) / BigDecimal(BigInt(1) << bp))) { throw new ChiselException(s"Invalid range with ${serialize}") } case _ => } case (firrtlir.Open(begin), firrtlir.Closed(end)) => - if(begin >= end) throw new ChiselException(s"Invalid range with ${serialize}") + if (begin >= end) throw new ChiselException(s"Invalid range with ${serialize}") case (firrtlir.Closed(begin), firrtlir.Open(end)) => - if(begin >= end) throw new ChiselException(s"Invalid range with ${serialize}") + if (begin >= end) throw new ChiselException(s"Invalid range with ${serialize}") case (firrtlir.Closed(begin), firrtlir.Closed(end)) => - if(begin > end) throw new ChiselException(s"Invalid range with ${serialize}") + if (begin > end) throw new ChiselException(s"Invalid range with ${serialize}") case _ => } override def toString: String = { val binaryPoint = firrtlBinaryPoint match { case firrtlir.IntWidth(n) => s"$n" - case _ => "?" + case _ => "?" } val lowerBoundString = lowerBound match { - case firrtlir.Closed(l) => s"[$l" - case firrtlir.Open(l) => s"($l" - case firrtlir.UnknownBound => s"[?" + case firrtlir.Closed(l) => s"[$l" + case firrtlir.Open(l) => s"($l" + case firrtlir.UnknownBound => s"[?" } val upperBoundString = upperBound match { - case firrtlir.Closed(l) => s"$l]" - case firrtlir.Open(l) => s"$l)" - case firrtlir.UnknownBound => s"?]" + case firrtlir.Closed(l) => s"$l]" + case firrtlir.Open(l) => s"$l)" + case firrtlir.UnknownBound => s"?]" } s"""range"$lowerBoundString,$upperBoundString.$binaryPoint"""" } @@ -487,8 +489,8 @@ sealed class IntervalRange( case Some(inc) => lower match { case firrtlir.Closed(n) => Some(n) - case firrtlir.Open(n) => Some(n + inc) - case _ => None + case firrtlir.Open(n) => Some(n + inc) + case _ => None } case _ => None @@ -503,8 +505,8 @@ sealed class IntervalRange( case Some(inc) => upper match { case firrtlir.Closed(n) => Some(n) - case firrtlir.Open(n) => Some(n - inc) - case _ => None + case firrtlir.Open(n) => Some(n - inc) + case _ => None } case _ => None @@ -528,16 +530,18 @@ sealed class IntervalRange( override def getWidth: Width = { width match { - case firrtlir.IntWidth(n) => KnownWidth(n.toInt) + case firrtlir.IntWidth(n) => KnownWidth(n.toInt) case firrtlir.UnknownWidth => UnknownWidth() } } private def doFirrtlOp(op: firrtlir.PrimOp, that: IntervalRange): IntervalRange = { - PrimOps.set_primop_type( - firrtlir.DoPrim(op, - Seq(firrtlir.Reference("a", this), firrtlir.Reference("b", that)), Nil,firrtlir.UnknownType) - ).tpe match { + PrimOps + .set_primop_type( + firrtlir + .DoPrim(op, Seq(firrtlir.Reference("a", this), firrtlir.Reference("b", that)), Nil, firrtlir.UnknownType) + ) + .tpe match { case i: firrtlir.IntervalType => IntervalRange(i.lower, i.upper, i.point) case other => sys.error("BAD!") } @@ -545,24 +549,27 @@ sealed class IntervalRange( private def doFirrtlDynamicShift(that: UInt, isLeft: Boolean): IntervalRange = { val uinttpe = that.widthOption match { - case None => firrtlir.UIntType(firrtlir.UnknownWidth) + case None => firrtlir.UIntType(firrtlir.UnknownWidth) case Some(w) => firrtlir.UIntType(firrtlir.IntWidth(w)) } - val op = if(isLeft) PrimOps.Dshl else PrimOps.Dshr - PrimOps.set_primop_type( - firrtlir.DoPrim(op, - Seq(firrtlir.Reference("a", this), firrtlir.Reference("b", uinttpe)), Nil,firrtlir.UnknownType) - ).tpe match { + val op = if (isLeft) PrimOps.Dshl else PrimOps.Dshr + PrimOps + .set_primop_type( + firrtlir + .DoPrim(op, Seq(firrtlir.Reference("a", this), firrtlir.Reference("b", uinttpe)), Nil, firrtlir.UnknownType) + ) + .tpe match { case i: firrtlir.IntervalType => IntervalRange(i.lower, i.upper, i.point) case other => sys.error("BAD!") } } private def doFirrtlOp(op: firrtlir.PrimOp, that: Int): IntervalRange = { - PrimOps.set_primop_type( - firrtlir.DoPrim(op, - Seq(firrtlir.Reference("a", this)), Seq(BigInt(that)), firrtlir.UnknownType) - ).tpe match { + PrimOps + .set_primop_type( + firrtlir.DoPrim(op, Seq(firrtlir.Reference("a", this)), Seq(BigInt(that)), firrtlir.UnknownType) + ) + .tpe match { case i: firrtlir.IntervalType => IntervalRange(i.lower, i.upper, i.point) case other => sys.error("BAD!") } @@ -596,7 +603,7 @@ sealed class IntervalRange( } private def adjustBoundValue(value: BigDecimal, binaryPointValue: Int): BigDecimal = { - if(binaryPointValue >= 0) { + if (binaryPointValue >= 0) { val maskFactor = BigDecimal(1 << binaryPointValue) val a = (value * maskFactor) val b = a.setScale(0, RoundingMode.DOWN) @@ -611,9 +618,9 @@ sealed class IntervalRange( binaryPoint match { case KnownBinaryPoint(binaryPointValue) => bound match { - case firrtlir.Open(value) => firrtlir.Open(adjustBoundValue(value, binaryPointValue)) + case firrtlir.Open(value) => firrtlir.Open(adjustBoundValue(value, binaryPointValue)) case firrtlir.Closed(value) => firrtlir.Closed(adjustBoundValue(value, binaryPointValue)) - case _ => bound + case _ => bound } case _ => firrtlir.UnknownBound } @@ -746,19 +753,22 @@ sealed class IntervalRange( override def merge(that: IntervalRange): IntervalRange = { val lowest = (this.getLowestPossibleValue, that.getLowestPossibleValue) match { case (Some(l1), Some(l2)) => - if(l1 < l2) { this.lower } else { that.lower } + if (l1 < l2) { this.lower } + else { that.lower } case _ => firrtlir.UnknownBound } val highest = (this.getHighestPossibleValue, that.getHighestPossibleValue) match { case (Some(l1), Some(l2)) => - if(l1 >= l2) { this.lower } else { that.lower } + if (l1 >= l2) { this.lower } + else { that.lower } case _ => firrtlir.UnknownBound } val newBinaryPoint = (this.firrtlBinaryPoint, that.firrtlBinaryPoint) match { case (firrtlir.IntWidth(b1), firrtlir.IntWidth(b2)) => - if(b1 > b2) { firrtlir.IntWidth(b1)} else { firrtlir.IntWidth(b2) } + if (b1 > b2) { firrtlir.IntWidth(b1) } + else { firrtlir.IntWidth(b2) } case _ => firrtlir.UnknownWidth } @@ -788,8 +798,21 @@ case class DefWire(sourceInfo: SourceInfo, id: Data) extends Definition case class DefReg(sourceInfo: SourceInfo, id: Data, clock: Arg) extends Definition case class DefRegInit(sourceInfo: SourceInfo, id: Data, clock: Arg, reset: Arg, init: Arg) extends Definition case class DefMemory(sourceInfo: SourceInfo, id: HasId, t: Data, size: BigInt) extends Definition -case class DefSeqMemory(sourceInfo: SourceInfo, id: HasId, t: Data, size: BigInt, readUnderWrite: fir.ReadUnderWrite.Value) extends Definition -case class DefMemPort[T <: Data](sourceInfo: SourceInfo, id: T, source: Node, dir: MemPortDirection, index: Arg, clock: Arg) extends Definition +case class DefSeqMemory( + sourceInfo: SourceInfo, + id: HasId, + t: Data, + size: BigInt, + readUnderWrite: fir.ReadUnderWrite.Value) + extends Definition +case class DefMemPort[T <: Data]( + sourceInfo: SourceInfo, + id: T, + source: Node, + dir: MemPortDirection, + index: Arg, + clock: Arg) + extends Definition @nowarn("msg=class Port") // delete when Port becomes private case class DefInstance(sourceInfo: SourceInfo, id: BaseModule, ports: Seq[Port]) extends Definition case class WhenBegin(sourceInfo: SourceInfo, pred: Arg) extends Command @@ -802,7 +825,10 @@ case class Attach(sourceInfo: SourceInfo, locs: Seq[Node]) extends Command case class ConnectInit(sourceInfo: SourceInfo, loc: Node, exp: Arg) extends Command case class Stop(id: stop.Stop, sourceInfo: SourceInfo, clock: Arg, ret: Int) extends Definition // Note this is just deprecated which will cause deprecation warnings, use @nowarn -@deprecated("This API should never have been public, for Module port reflection, use DataMirror.modulePorts", "Chisel 3.5") +@deprecated( + "This API should never have been public, for Module port reflection, use DataMirror.modulePorts", + "Chisel 3.5" +) case class Port(id: Data, dir: SpecifiedDirection) case class Printf(id: printf.Printf, sourceInfo: SourceInfo, clock: Arg, pable: Printable) extends Definition object Formal extends Enumeration { @@ -810,18 +836,30 @@ object Formal extends Enumeration { val Assume = Value("assume") val Cover = Value("cover") } -case class Verification[T <: VerificationStatement](id: T, op: Formal.Value, sourceInfo: SourceInfo, clock: Arg, - predicate: Arg, message: String) extends Definition +case class Verification[T <: VerificationStatement]( + id: T, + op: Formal.Value, + sourceInfo: SourceInfo, + clock: Arg, + predicate: Arg, + message: String) + extends Definition @nowarn("msg=class Port") // delete when Port becomes private abstract class Component extends Arg { - def id: BaseModule - def name: String + def id: BaseModule + def name: String def ports: Seq[Port] } @nowarn("msg=class Port") // delete when Port becomes private case class DefModule(id: RawModule, name: String, ports: Seq[Port], commands: Seq[Command]) extends Component @nowarn("msg=class Port") // delete when Port becomes private -case class DefBlackBox(id: BaseBlackBox, name: String, ports: Seq[Port], topDir: SpecifiedDirection, params: Map[String, Param]) extends Component +case class DefBlackBox( + id: BaseBlackBox, + name: String, + ports: Seq[Port], + topDir: SpecifiedDirection, + params: Map[String, Param]) + extends Component case class Circuit(name: String, components: Seq[Component], annotations: Seq[ChiselAnnotation], renames: RenameMap) { def firrtlAnnotations: Iterable[Annotation] = annotations.flatMap(_.toFirrtl.update(renames)) diff --git a/core/src/main/scala/chisel3/internal/prefix.scala b/core/src/main/scala/chisel3/internal/prefix.scala index 620d0864..1e4c5ff1 100644 --- a/core/src/main/scala/chisel3/internal/prefix.scala +++ b/core/src/main/scala/chisel3/internal/prefix.scala @@ -15,7 +15,6 @@ package chisel3.internal * } * * }}} - * */ private[chisel3] object prefix { // scalastyle:ignore @@ -51,7 +50,7 @@ private[chisel3] object prefix { // scalastyle:ignore // This causes extra prefixes to be added, and subsequently cleared in the // Module constructor. Thus, we need to just make sure if the previous push // was an incorrect one, to not pop off an empty stack - if(Builder.getPrefix.nonEmpty) Builder.popPrefix() + if (Builder.getPrefix.nonEmpty) Builder.popPrefix() ret } } @@ -65,7 +64,6 @@ private[chisel3] object prefix { // scalastyle:ignore * } * * }}} - * */ private[chisel3] object noPrefix { |
