diff --git a/.gitignore b/.gitignore index b4fc65d..9cc0d18 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ generated/ .idea target/ *.iml +*.swp diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index 00cf254..93e62b5 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -44,7 +44,7 @@ object Vec { * @note elements are NOT assigned by default and have no value */ def apply[T <: Data](n: Int, gen: T): Vec[T] = macro VecTransform.apply_ngen; - + def do_apply[T <: Data](n: Int, gen: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[T] = { if ( gen.isLit ) { Vec(Seq.fill(n)(gen)) @@ -152,6 +152,24 @@ object Vec { } } +class MonoLabelVec[T <: Data](gen: => T, length: Int) extends Vec[T](gen, length) { + override def _onModuleClose: Unit = { + sample_element.setRef(this, 0) + } + + override def cloneType: this.type = { + new MonoLabelVec(gen.cloneType, length).asInstanceOf[this.type] + } +} + +object MonoLabelVec { + def apply[T <: Data](n: Int, gen: T): Vec[T] = macro VecTransform.apply_ngen; + + def do_apply[T <: Data](n: Int, gen: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[T] = { + new MonoLabelVec(gen.chiselCloneType, n) + } +} + /** A vector (array) of [[Data]] elements. Provides hardware versions of various * collection transformation functions found in software array implementations. * @@ -161,8 +179,9 @@ object Vec { * @note Vecs, unlike classes in Scala's collection library, are propagated * intact to FIRRTL as a vector type, which may make debugging easier */ -sealed class Vec[T <: Data] private (gen: => T, val length: Int) +sealed class Vec[T <: Data] protected (gen: => T, val length: Int) extends Aggregate with VecLike[T] { + // Note: the constructor takes a gen() function instead of a Seq to enforce // that all elements must be the same and because it makes FIRRTL generation // simpler. @@ -244,6 +263,9 @@ sealed class Vec[T <: Data] private (gen: => T, val length: Int) } private[chisel3] def toType: String = s"${sample_element.toType}[$length]" + private[chisel3] override def toType(ctx: Component): String = { + s"${sample_element.toType(ctx)}[$length]" + } private[chisel3] lazy val flatten: IndexedSeq[Bits] = (0 until length).flatMap(i => this.apply(i).flatten) @@ -260,6 +282,10 @@ sealed class Vec[T <: Data] private (gen: => T, val length: Int) else self flatMap (e => List(e.toPrintable, PString(", "))) dropRight 1 PString("Vec(") + Printables(elts) + PString(")") } + + override def _onModuleClose: Unit = { + sample_element.setRefBinder(this) + } } /** A trait for [[Vec]]s containing common hardware generators for collection @@ -347,7 +373,7 @@ trait VecLike[T <: Data] extends collection.IndexedSeq[T] with HasId { * Record should only be extended by libraries and fairly sophisticated generators. * RTL writers should use [[Bundle]]. */ -abstract class Record extends Aggregate { +abstract class Record extends Aggregate with BitsLevelNamer { /** The collection of [[Data]] * @@ -385,6 +411,29 @@ abstract class Record extends Aggregate { elements.toIndexedSeq.reverse.map(e => eltPort(e._2)).mkString("{", ", ", "}") } + def slotsToNames(arg: Arg): Seq[String] = { + type Names = scala.collection.mutable.LinkedHashSet[String] + val names = new scala.collection.mutable.LinkedHashSet[String] + def slotsToSeq_(names: Names)(arg: Arg): Arg = arg match { + case ax: Slot => names += ax.name; slotsToSeq_(names)(ax.imm) + case ax: Node => slotsToSeq_(names)(ax.id.getRef) + case ax: Index => slotsToSeq_(names)(ax.imm) + case ax => ax + } + slotsToSeq_(names)(arg) + names.toSeq.reverse + } + + def namesToElt(names: Seq[String]): Data = { + var elt: Data = this + for(name <- names) elt match { + case ax: Record => + if(ax.elements contains name) elt = ax.elements(name) + case _ => + } + elt + } + private[chisel3] lazy val flatten = elements.toIndexedSeq.flatMap(_._2.flatten) // NOTE: This sets up dependent references, it can be done before closing the Module @@ -393,7 +442,11 @@ abstract class Record extends Aggregate { // identifier; however, Namespace sanitizes identifiers to make them legal for Firrtl/Verilog // which can cause collisions val _namespace = Namespace.empty - for ((name, elt) <- elements) { elt.setRef(this, _namespace.name(name)) } + + for ((name, elt) <- elements.toIndexedSeq.reverse) { + elt.setRef(this, _namespace.name(name)) + } + } private[chisel3] final def allElements: Seq[Element] = elements.toIndexedSeq.flatMap(_._2.allElements) @@ -442,11 +495,12 @@ class Bundle extends Record { final lazy val elements: ListMap[String, Data] = { val nameMap = LinkedHashMap[String, Data]() val seen = HashSet[Data]() + def isShadow(s:String) = s contains "shdw" for (m <- getPublicFields(classOf[Bundle])) { getBundleField(m) foreach { d => if (nameMap contains m.getName) { require(nameMap(m.getName) eq d) - } else if (!seen(d)) { + } else if (!seen(d) && !isShadow(m.getName)) { nameMap(m.getName) = d seen += d } @@ -455,6 +509,7 @@ class Bundle extends Record { ListMap(nameMap.toSeq sortWith { case ((an, a), (bn, b)) => (a._id > b._id) || ((a eq b) && (an > bn)) }: _*) } + /** Returns a field's contained user-defined Bundle element if it appears to * be one, otherwise returns None. */ @@ -464,6 +519,25 @@ class Bundle extends Record { case _ => None } + def elementsRec = { + var eltSets = new ListMap[String, Data] + eltSets ++= elements + elements.map { _._2 } match { + case elt: Record => eltSets ++= elt.elements + case _ => + } + eltSets + } + + /* + def renameLabelsOfClone(clone: this.type): Unit = + for( (name, elt) <- elements ) + HLevel.replace(elt, clone.elements.find( _._1 == name).get._2) + */ + + def renameLabelsOfClone(clone: this.type) : Unit = { + } + override def cloneType : this.type = { // If the user did not provide a cloneType method, try invoking one of // the following constructors, not all of which necessarily exist: @@ -472,13 +546,17 @@ class Bundle extends Record { // - A one-parameter constructor for a nested Bundle, with the enclosing // parent Module as the argument val constructor = this.getClass.getConstructors.head - try { + val dataClone: this.type = try { val args = Seq.fill(constructor.getParameterTypes.size)(null) - constructor.newInstance(args:_*).asInstanceOf[this.type] + val ret = constructor.newInstance(args:_*).asInstanceOf[this.type] + cpy_lbls(ret) + ret } catch { case e: java.lang.reflect.InvocationTargetException if e.getCause.isInstanceOf[java.lang.NullPointerException] => try { - constructor.newInstance(_parent.get).asInstanceOf[this.type] + val ret = constructor.newInstance(_parent.get).asInstanceOf[this.type] + cpy_lbls(ret) + ret } catch { case _: java.lang.reflect.InvocationTargetException | _: java.lang.IllegalArgumentException => Builder.exception(s"Parameterized Bundle ${this.getClass} needs cloneType method. You are probably using " + @@ -489,6 +567,15 @@ class Bundle extends Record { Builder.exception(s"Parameterized Bundle ${this.getClass} needs cloneType method") this } + renameLabelsOfClone(dataClone) + dataClone + } + + override def cpy_lbls(that: this.type): Unit = { + for ((name, elt) <- elements) { + elt.cpy_lbls(that.elements(name).asInstanceOf[elt.type]) + // that.elements(name).lbl_ = elt.lbl_ + } } /** Default "pretty-print" implementation @@ -505,3 +592,45 @@ private[core] object Bundle { "widthOption", "signalName", "signalPathName", "signalParent", "signalComponent") } + +trait BitsLevelNamer { + + def strTmp(s:String) = s contains "_T_" + def argIsTemp(arg: Arg): Boolean = arg match { + case ax: Ref => strTmp(ax.name) + case ax: ModuleIO => strTmp(ax.name) || strTmp(ax.mod.name) + case ax: Slot => !ax.imm.id.refSet || argIsTemp(ax.imm.id.getRef) || strTmp(ax.name) + case ax: Index => argIsTemp(ax.imm) || strTmp(ax.name) + case ax: Node => !ax.id.refSet || strTmp(ax.name) + case ax: LitArg => false + case ax: BindIndex => argIsTemp(ax.imm) + } + + + def nameBitsInLevels(namedRecord: Record, outerRecord: Record): Unit = { + val nameElts = namedRecord.elements.toIndexedSeq.reverse ++ outerRecord.elements.toIndexedSeq.reverse + for ((name, elt) <- nameElts) { + if(elt.lbl != null) { + elt.lbl.conf match { + case lx: HLevel if(lx.id.refSet) => + if(argIsTemp(lx.id.getRef) && (namedRecord.elements contains lx.id.getRef.name)) + lx.id.setRef(namedRecord, lx.id.getRef.name) + case lx: VLabel if(lx.id.refSet) => + if(argIsTemp(lx.id.getRef) && (namedRecord.elements contains lx.id.getRef.name)) + lx.id.setRef(namedRecord, lx.id.getRef.name) + case lx => + } + elt.lbl.integ match { + case lx: HLevel if(lx.id.refSet) => + if(argIsTemp(lx.id.getRef) && (namedRecord.elements contains lx.id.getRef.name)) + lx.id.setRef(namedRecord, lx.id.getRef.name) + case lx: VLabel if(lx.id.refSet) => + if(argIsTemp(lx.id.getRef) && (namedRecord.elements contains lx.id.getRef.name)) + lx.id.setRef(namedRecord, lx.id.getRef.name) + case lx => + } + } + } + } +} + diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index 2654359..d7b2546 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -5,10 +5,10 @@ package chisel3.core import scala.language.experimental.macros import chisel3.internal._ -import chisel3.internal.Builder.{pushCommand, pushOp, pushDeclass, pushEndorse} +import chisel3.internal.Builder.{pushCommand, pushOp, pushDeclass, pushEndorse, pushNext} import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, SourceInfoTransform, SourceInfoWhiteboxTransform, - UIntTransform, MuxTransform, DeclassifyTransform, EndorseTransform} + UIntTransform, MuxTransform, DeclassifyTransform, EndorseTransform, NextTransform} import chisel3.internal.firrtl.PrimOp._ // TODO: remove this once we have CompileOptions threaded through the macro system. import chisel3.core.ExplicitCompileOptions.NotStrict @@ -790,6 +790,14 @@ object Endorse { } } +object Next { + def apply[T <: Data](arg: T): T = macro NextTransform.apply[T] + def do_apply[T <: Data](arg: T)(implicit sourceInfo: SourceInfo): T = { + val dtype = arg.cloneType + pushNext(DefNext(sourceInfo, dtype, arg.ref)) + } +} + object Mux { /** Creates a mux, whose output is one of the inputs depending on the * value of the condition. diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index 1e3516d..a8e39b9 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -59,8 +59,11 @@ object Output { } } object Flipped { - def apply[T<:Data](source: T)(implicit compileOptions: CompileOptions): T = - apply(source, UnknownLabel) + def apply[T<:Data](source: T)(implicit compileOptions: CompileOptions): T = { + val target = source.chiselCloneType + Data.setFirrtlDirection(target, Data.getFirrtlDirection(source).flip) + Binding.bind(target, FlippedBinder, "Error: Cannot flip ") + } def apply[T<:Data](source: T, lbl: Label)(implicit compileOptions: CompileOptions): T = { val target = source.chiselCloneType @@ -151,6 +154,10 @@ abstract class Data extends HasId with HasLabel{ protected[chisel3] var lbl_ : Label = UnknownLabel def lbl = lbl_ + def setLabel(lb: Label): Unit = { + lbl_ = lb + } + private[core] def badConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = throwException(s"cannot connect ${this} and ${that}") private[chisel3] def connect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = { @@ -162,7 +169,7 @@ abstract class Data extends HasId with HasLabel{ } catch { case MonoConnect.MonoConnectException(message) => throwException( - s"Connection between sink ($this) and source ($that) failed @$message" + s"Connection between sink ($this) and source ($that) failed @$message si:${sourceInfo.makeMessage(x => x)}" ) } } else { @@ -178,7 +185,7 @@ abstract class Data extends HasId with HasLabel{ } catch { case BiConnect.BiConnectException(message) => throwException( - s"Connection between left ($this) and source ($that) failed @$message" + s"Connection between left ($this) and source ($that) failed @$message si:${sourceInfo.makeMessage(x => x)}" ) } } else { @@ -193,6 +200,10 @@ abstract class Data extends HasId with HasLabel{ private[core] def width: Width private[core] def legacyConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit + private[chisel3] def cpy_lbls(that: this.type): Unit = { + that.lbl_ = lbl_ + } + /** cloneType must be defined for any Chisel object extending Data. * It is responsible for constructing a basic copy of the object being cloned. * If cloneType needs to recursively clone elements of an object, it should call diff --git a/chiselFrontend/src/main/scala/chisel3/core/Label.scala b/chiselFrontend/src/main/scala/chisel3/core/Label.scala index 981114b..26a79b0 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Label.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Label.scala @@ -53,10 +53,53 @@ object FunLabel{ def apply(fname: String, ids: HasId*) = new FunLabel(fname, ids.toList) } +/* case class HLevel(id: HasId) extends LabelComp { def name = s"[[${id.getRef.name}]]H" def fullName(ctx: Component) = s"[[${id.getRef.fullName(ctx)}]]H" } +*/ + +class HLevel private(var id: HasId) extends LabelComp { + def name = s"[[${id.getRef.name}]]H" + def fullName(ctx: Component) = s"[[${id.getRef.fullName(ctx)}]]H" + /* + override def equals(that: Any) = that match { + case lx: HLevel => lx.id == this.id + case _ => false + } + override def hashCode = id.hashCode + */ +} + +object HLevel { + private val hlevels = new scala.collection.mutable.HashMap[HasId, HLevel] + def apply(id: HasId): HLevel = { + if(!(hlevels contains id)) + hlevels(id) = new HLevel(id) + hlevels(id) + } + def unapply(hl: HLevel) = Some(hl.id) + private[chisel3] def replace(oldId: HasId, newId: HasId) { + if(hlevels contains oldId) { + val oldHLevel = hlevels(oldId) + oldHLevel.id = newId + hlevels -= oldId + hlevels(newId) = oldHLevel + } + } +} + +case class IfL(id: HasId)(tc: LabelComp)(fc: LabelComp) extends LabelComp { + def name = s"IFL(${id.getRef.name})(${tc.name})(${fc.name})" + def fullName(ctx: Component) = + s"IFL(${id.getRef.fullName(ctx)})(${tc.fullName(ctx)})(${fc.fullName(ctx)})" +} + +case class VLabel(id: HasId) extends LabelComp { + def name = s"[[${id.getRef.name}]]V" + def fullName(ctx: Component) = s"[[${id.getRef.fullName(ctx)}]]V" +} object C { def apply(l: Label): LabelComp = l match { @@ -77,5 +120,13 @@ object I { } // These are not parsed by sFIRRTL and are only used internally -// case class JoinLabel(l: Label, r: Label) extends Label +case class JoinLabelComp(l: LabelComp, r: LabelComp) extends LabelComp { + def name = s"${l.name} join ${r.name}" + def fullName(ctx: Component) = s"${l.fullName(ctx)} join ${r.fullName(ctx)}" +} + +case class MeetLabelComp(l: LabelComp, r: LabelComp) extends LabelComp { + def name = s"${l.name} meet ${r.name}" + def fullName(ctx: Component) = s"${l.fullName(ctx)} meet ${r.fullName(ctx)}" +} // case class MeetLabel(l: Label, r: Label) extends Label diff --git a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala index af586f1..a278c3c 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala @@ -13,21 +13,22 @@ import chisel3.core.ExplicitCompileOptions.NotStrict object Mem { @deprecated("Mem argument order should be size, t; this will be removed by the official release", "chisel3") - def apply[T <: Data](t: T, size: Int, l: Label): Mem[T] = do_apply(size, t, l)(UnlocatableSourceInfo) + def apply[T <: Data](t: T, size: Int, lbl: Label): Mem[T] = do_apply(size, t, lbl)(UnlocatableSourceInfo) /** Creates a combinational-read, sequential-write [[Mem]]. * * @param size number of elements in the memory * @param t data type of memory element */ - def apply[T <: Data](size: Int, t: T, l: Label=UnknownLabel): Mem[T] = macro MemTransform.apply[T] - def do_apply[T <: Data](size: Int, t: T, l: Label)(implicit sourceInfo: SourceInfo): Mem[T] = { + def apply[T <: Data](size: Int, t: T): Mem[T] = do_apply(size, t, UnknownLabel)(UnlocatableSourceInfo) + def apply[T <: Data](size: Int, t: T, lbl: Label): Mem[T] = macro MemTransform.apply[T] + def do_apply[T <: Data](size: Int, t: T, lbl: Label)(implicit sourceInfo: SourceInfo): Mem[T] = { val mt = t.chiselCloneType Binding.bind(mt, NoDirectionBinder, "Error: fresh t") // TODO(twigg): Remove need for this Binding val mem = new Mem(mt, size) - pushCommand(DefMemory(sourceInfo, mem, mt, size, l)) // TODO multi-clock + pushCommand(DefMemory(sourceInfo, mem, mt, lbl, size)) // TODO multi-clock mem } } @@ -113,22 +114,23 @@ sealed class Mem[T <: Data](t: T, length: Int) extends MemBase(t, length) object SeqMem { @deprecated("SeqMem argument order should be size, t; this will be removed by the official release", "chisel3") - def apply[T <: Data](t: T, size: Int, l: Label): SeqMem[T] = do_apply(size, t, l)(DeprecatedSourceInfo) + def apply[T <: Data](t: T, size: Int, lbl: Label): SeqMem[T] = do_apply(size, t, lbl)(DeprecatedSourceInfo) /** Creates a sequential-read, sequential-write [[SeqMem]]. * * @param size number of elements in the memory * @param t data type of memory element */ - def apply[T <: Data](size: Int, t: T, l: Label=UnknownLabel): SeqMem[T] = macro MemTransform.apply[T] + def apply[T <: Data](size: Int, t: T, lbl: Label): SeqMem[T] = macro MemTransform.apply[T] + def apply[T <: Data](size: Int, t: T): SeqMem[T] = do_apply(size, t, UnknownLabel)(DeprecatedSourceInfo) - def do_apply[T <: Data](size: Int, t: T, l: Label)(implicit sourceInfo: SourceInfo): SeqMem[T] = { + def do_apply[T <: Data](size: Int, t: T, lbl: Label)(implicit sourceInfo: SourceInfo): SeqMem[T] = { val mt = t.chiselCloneType Binding.bind(mt, NoDirectionBinder, "Error: fresh t") // TODO(twigg): Remove need for this Binding val mem = new SeqMem(mt, size) - pushCommand(DefSeqMemory(sourceInfo, mem, mt, size, l)) // TODO multi-clock + pushCommand(DefSeqMemory(sourceInfo, mem, mt, lbl, size)) // TODO multi-clock mem } } diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala index e396edc..50a6a77 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -220,6 +220,13 @@ extends HasId { // All suggestions are in, force names to every node. _ids.foreach(_.forceName(default="_T", _namespace)) + + _commands.foreach { _ match { + case cmd: DefMemory => + cmd.t.setRef(cmd.id.getRef) + case _ => + }} + _ids.foreach(_._onModuleClose) this } diff --git a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala index 416c664..7df012b 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala @@ -79,7 +79,13 @@ object Reg { pushCommand(DefRegInit(sourceInfo, x, clock, Node(x._parent.get.reset), init.ref, lbl)) } if (next != null) { - Binding.checkSynthesizable(next, s"'next' ($next)") + try { + Binding.checkSynthesizable(next, s"'next' ($next)") + } catch { + case (e: Exception) => + val inf = s"badness info: ${sourceInfo.makeMessage(x=>x)}\n" + throw new Exception(inf + e.getMessage()) + } x := next } x diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala index 26beb6b..5878d4e 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala @@ -66,6 +66,7 @@ trait InstanceId { def parentModName: String } + private[chisel3] trait HasId extends InstanceId { private[chisel3] def _onModuleClose: Unit = {} // scalastyle:ignore method.name private[chisel3] val _parent: Option[Module] = Builder.currentModule @@ -105,7 +106,15 @@ private[chisel3] trait HasId extends InstanceId { 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 setRefBinder(parent: HasId): Unit = setRef(BindIndex(Node(parent))) + // private[chisel3] def setRef(parent: HasId, names: Seq[String]): Unit = { + // var newRef = Node(parent) + // for(name <- names) { + // newRef = Slot(Node(newRef), name) + // } + // } private[chisel3] def getRef: Arg = _ref.get + private[chisel3] def refSet: Boolean = !_ref.isEmpty // Implementation of public methods. def instanceName: String = _parent match { @@ -210,6 +219,12 @@ private[chisel3] object Builder { pushCommand(cmd).id } + def pushNext[ T <: Data](cmd: DefNext[T]): T = { + // Bind each element of the returned Data to being a Op + Binding.bind(cmd.id, OpBinder(forcedModule), "Error: During op creation, fresh result") + pushCommand(cmd).id + } + def errors: ErrorLog = dynamicContext.errors def error(m: => String): Unit = errors.error(m) def warning(m: => String): Unit = errors.warning(m) diff --git a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala index 29b67a0..47926bd 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala @@ -49,14 +49,17 @@ object PrimOp { val AsClockOp = PrimOp("asClock") } + abstract class Arg { def fullName(ctx: Component): String = name def name: String + def pprint: String } case class Node(id: HasId) extends Arg { override def fullName(ctx: Component): String = id.getRef.fullName(ctx) def name: String = id.getRef.name + def pprint = s"Node(${id.getRef.pprint})" } abstract class LitArg(val num: BigInt, widthArg: Width) extends Arg { @@ -68,10 +71,12 @@ abstract class LitArg(val num: BigInt, widthArg: Width) extends Arg { 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.") } + def pprint = s"LitArg(${num}, ${widthArg})" } case class ILit(n: BigInt) extends Arg { def name: String = n.toString + def pprint = s"ILit(${n})" } case class ULit(n: BigInt, w: Width) extends LitArg(n, w) { @@ -97,18 +102,28 @@ case class FPLit(n: BigInt, w: Width, binaryPoint: BinaryPoint) extends LitArg(n def minWidth: Int = 1 + n.bitLength } -case class Ref(name: String) extends Arg +case class Ref(name: String) extends Arg { + def pprint = s"Ref(${name})" +} case class ModuleIO(mod: Module, name: String) extends Arg { override def fullName(ctx: Component): String = if (mod eq ctx.id) name else s"${mod.getRef.name}.$name" + def pprint = s"ModuleIO(${mod.name}, ${name})" } case class Slot(imm: Node, name: String) extends Arg { override def fullName(ctx: Component): String = - if (imm.fullName(ctx).isEmpty) name else s"${imm.fullName(ctx)}.${name}" + s"${imm.fullName(ctx)}.${name}" + def pprint = s"Slot(${imm.pprint}, ${name})" } case class Index(imm: Arg, value: Arg) extends Arg { def name: String = s"[$value]" override def fullName(ctx: Component): String = s"${imm.fullName(ctx)}[${value.fullName(ctx)}]" + def pprint = s"Index(${imm.name}, ${value.name})" +} +case class BindIndex(imm: Arg) extends Arg { + def name: String = s"[_]" + override def fullName(ctx: Component): String = s"${imm.fullName(ctx)}[_]" + def pprint = s"Index(${imm.name}, _)" } sealed trait Bound @@ -253,12 +268,13 @@ abstract class Definition extends Command { case class DefPrim[T <: Data](sourceInfo: SourceInfo, id: T, op: PrimOp, args: Arg*) extends Definition case class DefDeclass[T <: Data](sourceInfo: SourceInfo, id: T, arg: Arg, lbl: Label) extends Definition case class DefEndorse[T <: Data](sourceInfo: SourceInfo, id: T, arg: Arg, lbl: Label) extends Definition +case class DefNext[T <: Data](sourceInfo: SourceInfo, id: T, arg: Arg) extends Definition case class DefInvalid(sourceInfo: SourceInfo, arg: Arg) extends Command case class DefWire(sourceInfo: SourceInfo, id: Data, lbl: Label) extends Definition case class DefReg(sourceInfo: SourceInfo, id: Data, clock: Arg, lbl: Label) extends Definition case class DefRegInit(sourceInfo: SourceInfo, id: Data, clock: Arg, reset: Arg, init: Arg, lbl: Label) extends Definition -case class DefMemory(sourceInfo: SourceInfo, id: HasId, t: Data, size: Int, lbl: Label) extends Definition -case class DefSeqMemory(sourceInfo: SourceInfo, id: HasId, t: Data, size: Int, lbl: Label) extends Definition +case class DefMemory(sourceInfo: SourceInfo, id: HasId, t: Data, lbl: Label, size: Int) extends Definition +case class DefSeqMemory(sourceInfo: SourceInfo, id: HasId, t: Data, lbl: Label, size: Int) extends Definition case class DefMemPort[T <: Data](sourceInfo: SourceInfo, id: T, source: Node, dir: MemPortDirection, index: Arg, clock: Arg) extends Definition case class DefInstance(sourceInfo: SourceInfo, id: Module, ports: Seq[Port]) extends Definition case class WhenBegin(sourceInfo: SourceInfo, pred: Arg) extends Command @@ -273,6 +289,7 @@ abstract class Component extends Arg { def id: Module def name: String def ports: Seq[Port] + def pprint = s"Component(${id.name}, ${name}, ...)" } case class DefModule(id: Module, name: String, ports: Seq[Port], commands: Seq[Command]) extends Component case class DefBlackBox(id: Module, name: String, ports: Seq[Port], params: Map[String, Param]) extends Component diff --git a/coreMacros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala b/coreMacros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala index 1d7ce76..9dbd158 100644 --- a/coreMacros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala +++ b/coreMacros/src/main/scala/chisel3/internal/sourceinfo/SourceInfoTransform.scala @@ -54,8 +54,8 @@ class InstTransform(val c: Context) extends SourceInfoTransformMacro { class MemTransform(val c: Context) extends SourceInfoTransformMacro { import c.universe._ - def apply[T: c.WeakTypeTag](size: c.Tree, t: c.Tree, l: c.Tree): c.Tree = { - q"$thisObj.do_apply($size, $t, $l)($implicitSourceInfo)" + def apply[T: c.WeakTypeTag](size: c.Tree, t: c.Tree, lbl: c.Tree): c.Tree = { + q"$thisObj.do_apply($size, $t, $lbl)($implicitSourceInfo)" } } @@ -83,6 +83,14 @@ class EndorseTransform(val c: Context) extends SourceInfoTransformMacro { } } +class NextTransform(val c: Context) extends SourceInfoTransformMacro { + import c.universe._ + def apply[T: c.WeakTypeTag](arg: c.Tree): c.Tree = { + val tpe = weakTypeOf[T] + q"$thisObj.do_apply[$tpe]($arg)($implicitSourceInfo)" + } +} + class MuxTransform(val c: Context) extends SourceInfoTransformMacro { import c.universe._ def apply[T: c.WeakTypeTag](cond: c.Tree, con: c.Tree, alt: c.Tree): c.Tree = { diff --git a/src/main/scala/chisel3/ChiselExecutionOptions.scala b/src/main/scala/chisel3/ChiselExecutionOptions.scala index 6f58153..4a9cf95 100644 --- a/src/main/scala/chisel3/ChiselExecutionOptions.scala +++ b/src/main/scala/chisel3/ChiselExecutionOptions.scala @@ -13,7 +13,8 @@ import firrtl.{ExecutionOptionsManager, ComposableOptions} * @note this extends FirrtlExecutionOptions which extends CommonOptions providing easy access to down chain options */ case class ChiselExecutionOptions( - runFirrtlCompiler: Boolean = true + runFirrtlCompiler: Boolean = true, + compileTopOnly: Boolean = false // var runFirrtlAsProcess: Boolean = false ) extends ComposableOptions @@ -30,5 +31,12 @@ trait HasChiselExecutionOptions { chiselOptions = chiselOptions.copy(runFirrtlCompiler = false) } .text("Stop after chisel emits chirrtl file") + + parser.opt[Unit]("top-def-only") + .abbr("tdf") + .foreach { _ => + chiselOptions = chiselOptions.copy(compileTopOnly = true) + } + .text("Only emit the def of the top-level module to support modular label-checking") } diff --git a/src/main/scala/chisel3/Driver.scala b/src/main/scala/chisel3/Driver.scala index 7bdb4d6..8b9a2b6 100644 --- a/src/main/scala/chisel3/Driver.scala +++ b/src/main/scala/chisel3/Driver.scala @@ -90,14 +90,14 @@ object Driver extends BackendCompilationUtilities { */ def elaborate[T <: Module](gen: () => T): Circuit = internal.Builder.build(Module(gen())) - def emit[T <: Module](gen: () => T): String = Emitter.emit(elaborate(gen)) + def emit[T <: Module](gen: () => T): String = Emitter.emit(elaborate(gen), false) - def emit[T <: Module](ir: Circuit): String = Emitter.emit(ir) + def emit[T <: Module](ir: Circuit): String = Emitter.emit(ir, false) - def dumpFirrtl(ir: Circuit, optName: Option[File]): File = { + def dumpFirrtl(ir: Circuit, optName: Option[File], onlyTop: Boolean = false): File = { val f = optName.getOrElse(new File(ir.name + ".fir")) val w = new FileWriter(f) - w.write(Emitter.emit(ir)) + w.write(Emitter.emit(ir, onlyTop)) w.close() f } @@ -132,7 +132,7 @@ object Driver extends BackendCompilationUtilities { val chiselOptions = optionsManager.chiselOptions // use input because firrtl will be reading this - val firrtlString = Emitter.emit(circuit) + val firrtlString = Emitter.emit(circuit, chiselOptions.compileTopOnly) val firrtlFileName = firrtlOptions.getInputFileName(optionsManager) val firrtlFile = new File(firrtlFileName) diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala index d338d9a..8a094e2 100644 --- a/src/main/scala/chisel3/compatibility.scala +++ b/src/main/scala/chisel3/compatibility.scala @@ -14,11 +14,35 @@ package object Chisel { // scalastyle:ignore package.object.name implicit val defaultCompileOptions = chisel3.core.ExplicitCompileOptions.NotStrict type Direction = chisel3.core.Direction + type Label = chisel3.core.Label + val Label = chisel3.core.Label + val UnknownLabel = chisel3.core.UnknownLabel + val UnknownLabelComp = chisel3.core.UnknownLabelComp + val Level = chisel3.core.Level + val FunLabel = chisel3.core.FunLabel + val HLevel = chisel3.core.HLevel + val VLabel = chisel3.core.VLabel + val JoinLabelComp = chisel3.core.JoinLabelComp + val MeetLabelComp = chisel3.core.MeetLabelComp + val Declassify = chisel3.core.Declassify + val Endorse = chisel3.core.Endorse + val Next = chisel3.core.Next + + + // Not originally part of compatibility.scala + val Input = chisel3.core.Input + val Output = chisel3.core.Output + + // Components + val C = chisel3.core.C + val I = chisel3.core.I + val INPUT = chisel3.core.Direction.Input val OUTPUT = chisel3.core.Direction.Output val NODIR = chisel3.core.Direction.Unspecified object Flipped { def apply[T<:Data](target: T): T = chisel3.core.Flipped[T](target) + def apply[T<:Data](target: T, lbl: Label): T = chisel3.core.Flipped[T](target, lbl) } // TODO: Possibly move the AddDirectionToData class here? implicit class AddDirMethodToData[T<:Data](val target: T) extends AnyVal { @@ -41,6 +65,8 @@ package object Chisel { // scalastyle:ignore package.object.name val Vec = chisel3.core.Vec type Vec[T <: Data] = chisel3.core.Vec[T] type VecLike[T <: Data] = chisel3.core.VecLike[T] + val MonoLabelVec = chisel3.core.MonoLabelVec + type MonoLabelVec[T <: Data] = chisel3.core.MonoLabelVec[T] type Record = chisel3.core.Record type Bundle = chisel3.core.Bundle @@ -71,11 +97,12 @@ package object Chisel { // scalastyle:ignore package.object.name def apply(dir: Direction, width: Int): UInt = apply(dir, width.W) /** Create a UInt with a specified direction, but unspecified width - compatibility with Chisel2. */ def apply(dir: Direction): UInt = apply(dir, Width()) - def apply(dir: Direction, width: Width): UInt = { - val result = apply(width) + def apply(dir: Direction, width: Width): UInt = apply(dir, width, UnknownLabel) + def apply(dir: Direction, width: Width, lbl:Label): UInt = { + val result = apply(width, lbl) dir match { - case chisel3.core.Direction.Input => chisel3.core.Input(result) - case chisel3.core.Direction.Output => chisel3.core.Output(result) + case chisel3.core.Direction.Input => chisel3.core.Input(result, lbl) + case chisel3.core.Direction.Output => chisel3.core.Output(result, lbl) case chisel3.core.Direction.Unspecified => result } } @@ -130,11 +157,11 @@ package object Chisel { // scalastyle:ignore package.object.name def apply(x: Boolean): Bool = x.B /** Create a UInt with a specified direction and width - compatibility with Chisel2. */ - def apply(dir: Direction): Bool = { - val result = apply() + def apply(dir: Direction, lbl:Label=UnknownLabel): Bool = { + val result = apply(lbl) dir match { - case chisel3.core.Direction.Input => chisel3.core.Input(result) - case chisel3.core.Direction.Output => chisel3.core.Output(result) + case chisel3.core.Direction.Input => chisel3.core.Input(result, lbl) + case chisel3.core.Direction.Output => chisel3.core.Output(result, lbl) case chisel3.core.Direction.Unspecified => result } } diff --git a/src/main/scala/chisel3/internal/firrtl/Emitter.scala b/src/main/scala/chisel3/internal/firrtl/Emitter.scala index 48a2e9b..5700fd7 100644 --- a/src/main/scala/chisel3/internal/firrtl/Emitter.scala +++ b/src/main/scala/chisel3/internal/firrtl/Emitter.scala @@ -14,10 +14,10 @@ import chisel3.core.HLevel import chisel3.core.Data private[chisel3] object Emitter { - def emit(circuit: Circuit): String = new Emitter(circuit).toString + def emit(circuit: Circuit, compileTopOnly: Boolean): String = new Emitter(circuit, compileTopOnly).toString } -private class Emitter(circuit: Circuit) { +private class Emitter(circuit: Circuit, compileTopOnly: Boolean) { override def toString: String = res.toString private def emitPort(e: Port, ctx:Component): String = @@ -32,11 +32,13 @@ private class Emitter(circuit: Circuit) { case e: DefEndorse[_] => val lbl_s = e.lbl.fullName(ctx) s"node ${e.name} ${lbl_s} = endorse(${e.arg.fullName(ctx)}, ${lbl_s})" - case e: DefWire => s"wire ${e.name} : ${e.lbl.fullName(ctx)}${e.id.toType}" - case e: DefReg => s"reg ${e.name} : ${e.lbl.fullName(ctx)}${e.id.toType}, ${e.clock.fullName(ctx)}" - case e: DefRegInit => s"reg ${e.name} : ${e.lbl.fullName(ctx)}${e.id.toType}, ${e.clock.fullName(ctx)} with : (reset => (${e.reset.fullName(ctx)}, ${e.init.fullName(ctx)}))" - case e: DefMemory => s"cmem ${e.name} : ${e.lbl.fullName(ctx)}${e.t.toType}[${e.size}]" - case e: DefSeqMemory => s"smem ${e.name} : ${e.lbl.fullName(ctx)}${e.t.toType}[${e.size}]" + case e: DefNext[_] => + s"node ${e.name} = next(${e.arg.fullName(ctx)})" + case e: DefWire => s"wire ${e.name} : ${e.lbl.fullName(ctx)}${e.id.toType(ctx)}" + case e: DefReg => s"reg ${e.name} : ${e.lbl.fullName(ctx)}${e.id.toType(ctx)}, ${e.clock.fullName(ctx)}" + case e: DefRegInit => s"reg ${e.name} : ${e.lbl.fullName(ctx)}${e.id.toType(ctx)}, ${e.clock.fullName(ctx)} with : (reset => (${e.reset.fullName(ctx)}, ${e.init.fullName(ctx)}))" + case e: DefMemory => s"cmem ${e.name} : ${e.lbl.fullName(ctx)}${e.t.toType(ctx)}[${e.size}]" + case e: DefSeqMemory => s"smem ${e.name} : ${e.lbl.fullName(ctx)}${e.t.toType(ctx)}[${e.size}]" case e: DefMemPort[_] => s"${e.dir} mport ${e.name} = ${e.source.fullName(ctx)}[${e.index.fullName(ctx)}], ${e.clock.fullName(ctx)}" case e: Connect => s"${e.loc.fullName(ctx)} <= ${e.exp.fullName(ctx)}" case e: BulkConnect => s"${e.loc1.fullName(ctx)} <- ${e.loc2.fullName(ctx)}" @@ -98,6 +100,16 @@ private class Emitter(circuit: Circuit) { body.toString() } + private def modulePorts(m: Component): String = { + val body = new StringBuilder + withIndent { + for (p <- m.ports) + body ++= newline + emitPort(p,m) + body ++= newline + } + body.toString() + } + /** Returns the FIRRTL declaration and body of a module, or nothing if it's a * duplicate of something already emitted (on the basis of simple string * matching). @@ -110,6 +122,14 @@ private class Emitter(circuit: Circuit) { sb.result } + private def emitDecl(m: Component): String = { + // Emit just the declaration and ports for modular label-checking. + val sb = new StringBuilder + sb.append(moduleDecl(m)) + sb.append(modulePorts(m)) + sb.result + } + private var indentLevel = 0 private def newline = "\n" + (" " * indentLevel) private def indent(): Unit = indentLevel += 1 @@ -119,6 +139,14 @@ private class Emitter(circuit: Circuit) { private val res = new StringBuilder() res ++= s";${Driver.chiselVersionString}\n" res ++= s"circuit ${circuit.name} : " - withIndent { circuit.components.foreach(c => res ++= emit(c)) } + if(compileTopOnly) { + withIndent { circuit.components.foreach(c => + if(c.name == circuit.name) res ++= emit(c) + else res ++= emitDecl(c) + ) + } + } else { + withIndent { circuit.components.foreach(c => res ++= emit(c)) } + } res ++= newline } diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala index e1661b3..6863a44 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -30,8 +30,13 @@ package object chisel3 { // scalastyle:ignore package.object.name val Level = chisel3.core.Level val FunLabel = chisel3.core.FunLabel val HLevel = chisel3.core.HLevel + val VLabel = chisel3.core.VLabel + val JoinLabelComp = chisel3.core.JoinLabelComp + val MeetLabelComp = chisel3.core.MeetLabelComp + val IfL = chisel3.core.IfL val Declassify = chisel3.core.Declassify val Endorse = chisel3.core.Endorse + val Next = chisel3.core.Next // Components val C = chisel3.core.C @@ -41,6 +46,8 @@ package object chisel3 { // scalastyle:ignore package.object.name type Aggregate = chisel3.core.Aggregate val Vec = chisel3.core.Vec type Vec[T <: Data] = chisel3.core.Vec[T] + val MonoLabelVec = chisel3.core.MonoLabelVec + type MonoLabelVec[T <: Data] = chisel3.core.MonoLabelVec[T] type VecLike[T <: Data] = chisel3.core.VecLike[T] type Bundle = chisel3.core.Bundle type Record = chisel3.core.Record diff --git a/src/main/scala/chisel3/util/Arbiter.scala b/src/main/scala/chisel3/util/Arbiter.scala index 7e049c9..3cf7d26 100644 --- a/src/main/scala/chisel3/util/Arbiter.scala +++ b/src/main/scala/chisel3/util/Arbiter.scala @@ -15,15 +15,16 @@ import chisel3.core.ExplicitCompileOptions.NotStrict * @param gen data type * @param n number of inputs */ -class ArbiterIO[T <: Data](gen: T, n: Int) extends Bundle { - val in = Flipped(Vec(n, Decoupled(gen))) - val out = Decoupled(gen) - val chosen = Output(UInt(log2Up(n).W)) +class ArbiterIO[T <: Data](gen: T, out_gen: T, n: Int, inl: Label, outl: Label) extends Bundle { + val in = Flipped(Vec(n, Decoupled(gen, inl, inl))) + val out = Decoupled(out_gen, outl, outl) + val chosen = Output(UInt(log2Up(n).W), outl) + def this(gen: T, n: Int) = this(gen, gen, n, UnknownLabel, UnknownLabel) } /** Arbiter Control determining which producer has access */ -private object ArbiterCtrl { +object ArbiterCtrl { def apply(request: Seq[Bool]): Seq[Bool] = request.length match { case 0 => Seq() case 1 => Seq(true.B) @@ -31,10 +32,11 @@ private object ArbiterCtrl { } } -abstract class LockingArbiterLike[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool]) extends Module { +abstract class LockingArbiterLike[T <: Data](gen: T, out_gen: T, n: Int, count: Int, + needsLock: Option[T => Bool], inl: Label, outl: Label) extends Module { protected def grant: Seq[Bool] protected def choice: UInt - val io = IO(new ArbiterIO(gen, n)) + val io = IO(new ArbiterIO(gen, out_gen, n, inl, outl)) io.chosen := choice io.out.valid := io.in(io.chosen).valid @@ -58,10 +60,14 @@ abstract class LockingArbiterLike[T <: Data](gen: T, n: Int, count: Int, needsLo for ((in, g) <- io.in zip grant) in.ready := g && io.out.ready } + + def this(gen: T, n: Int, count: Int, needsLock: Option[T=>Bool]) + = this(gen, gen, n, count, needsLock, UnknownLabel, UnknownLabel) } -class LockingRRArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool] = None) - extends LockingArbiterLike[T](gen, n, count, needsLock) { +class LockingRRArbiter[T <: Data](gen: T, out_gen: T, n: Int, count: Int, + inl: Label, outl: Label, needsLock: Option[T => Bool]) + extends LockingArbiterLike[T](gen, out_gen, n, count, needsLock, inl, outl) { private lazy val lastGrant = RegEnable(io.chosen, io.out.fire()) private lazy val grantMask = (0 until n).map(_.asUInt > lastGrant) private lazy val validMask = io.in zip grantMask map { case (in, g) => in.valid && g } @@ -76,15 +82,22 @@ class LockingRRArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[ when (io.in(i).valid) { choice := i.asUInt } for (i <- n-1 to 1 by -1) when (validMask(i)) { choice := i.asUInt } + + def this(gen: T, n: Int, count: Int, needsLock: Option[T => Bool ] = None) = + this(gen, gen, n, count, UnknownLabel, UnknownLabel, needsLock) } -class LockingArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool] = None) - extends LockingArbiterLike[T](gen, n, count, needsLock) { +class LockingArbiter[T <: Data](gen: T, out_gen: T, n: Int, count: Int, + inl: Label, outl: Label, needsLock: Option[T => Bool]) + extends LockingArbiterLike[T](gen, out_gen, n, count, needsLock, inl, outl) { protected def grant: Seq[Bool] = ArbiterCtrl(io.in.map(_.valid)) override protected lazy val choice = Wire(init=(n-1).asUInt) for (i <- n-2 to 0 by -1) when (io.in(i).valid) { choice := i.asUInt } + + def this(gen: T, n: Int, count: Int, needsLock: Option[T => Bool] = None) = + this(gen, gen, n, count, UnknownLabel, UnknownLabel, needsLock) } /** Hardware module that is used to sequence n producers into 1 consumer. @@ -97,7 +110,10 @@ class LockingArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T * consumer.io.in <> arb.io.out * }}} */ -class RRArbiter[T <: Data](gen:T, n: Int) extends LockingRRArbiter[T](gen, n, 1) +class RRArbiter[T <: Data](gen:T, out_gen: T, n: Int, inl: Label, outl: Label) + extends LockingRRArbiter[T](gen, out_gen, n, 1, inl, outl, None) { + def this(gen: T, n: Int) = this(gen, gen, n, UnknownLabel, UnknownLabel) +} /** Hardware module that is used to sequence n producers into 1 consumer. * Priority is given to lower producer. @@ -109,9 +125,11 @@ class RRArbiter[T <: Data](gen:T, n: Int) extends LockingRRArbiter[T](gen, n, 1) * consumer.io.in <> arb.io.out * }}} */ -class Arbiter[T <: Data](gen: T, n: Int) extends Module { - val io = IO(new ArbiterIO(gen, n)) +class Arbiter[T <: Data](gen: T, out_gen: T, n: Int, inl: Label, outl: Label) extends Module { + val io = IO(new ArbiterIO(gen, out_gen, n, inl, outl)) + def this(gen: T, n: Int) = this(gen, gen, n, UnknownLabel, UnknownLabel) + io.chosen := (n-1).asUInt io.out.bits := io.in(n-1).bits for (i <- n-2 to 0 by -1) { diff --git a/src/main/scala/chisel3/util/Counter.scala b/src/main/scala/chisel3/util/Counter.scala index 6d59eaa..4c02e31 100644 --- a/src/main/scala/chisel3/util/Counter.scala +++ b/src/main/scala/chisel3/util/Counter.scala @@ -10,9 +10,9 @@ import chisel3._ * @param n number of counts before the counter resets (or one more than the * maximum output value of the counter), need not be a power of two */ -class Counter(val n: Int) { +class Counter(val n: Int, l: Label=UnknownLabel) { require(n >= 0) - val value = if (n > 1) Reg(init=0.U(log2Up(n).W)) else 0.U + val value = if (n > 1) Reg(init=0.U(log2Up(n).W), lbl = l) else 0.U /** Increment the counter, returning whether the counter currently is at the * maximum and will wrap. The incremented value is registered and will be @@ -36,7 +36,7 @@ object Counter { /** Instantiate a [[Counter! counter]] with the specified number of counts. */ - def apply(n: Int): Counter = new Counter(n) + def apply(n: Int, l: Label = UnknownLabel): Counter = new Counter(n, l) /** Instantiate a [[Counter! counter]] with the specified number of counts and a gate. * diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 2e874a1..81f55b5 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -9,17 +9,28 @@ import chisel3._ // TODO: remove this once we have CompileOptions threaded through the macro system. import chisel3.core.ExplicitCompileOptions.NotStrict +import chisel3.core.{HLevel, VLabel} + /** An I/O Bundle containing 'valid' and 'ready' signals that handshake * the transfer of data stored in the 'bits' subfield. * The base protocol implied by the directionality is that the consumer * uses the flipped interface. Actual semantics of ready/valid are * enforced via use of concrete subclasses. */ -abstract class ReadyValidIO[+T <: Data](gen: T) extends Bundle +abstract class ReadyValidIO[+T <: Data](gen: T, val rdyl: Label=UnknownLabel, val vall: Label=UnknownLabel) extends Bundle { - val ready = Input(Bool()) - val valid = Output(Bool()) + val ready = Input(Bool(), rdyl) + val valid = Output(Bool(), vall) val bits = Output(gen.chiselCloneType) + + override def _onModuleClose: Unit = { + super._onModuleClose + bits match { + case bx: Record => + nameBitsInLevels(bx, this) + case _ => + } + } } object ReadyValidIO { @@ -70,16 +81,23 @@ object ReadyValidIO { * to accept the data this cycle. No requirements are placed on the signaling * of ready or valid. */ -class DecoupledIO[+T <: Data](gen: T) extends ReadyValidIO[T](gen) +class DecoupledIO[+T <: Data](gen: T, rdyl: Label, vall: Label) extends ReadyValidIO[T](gen, rdyl, vall) { - override def cloneType: this.type = new DecoupledIO(gen).asInstanceOf[this.type] + override def cloneType: this.type = { + val ret = new DecoupledIO(gen, rdyl, vall).asInstanceOf[this.type] + renameLabelsOfClone(ret) + // cpy_lbls(ret) + // bits.cpy_lbls(ret.bits) + ret + } + def this(gen: T) = this(gen, UnknownLabel, UnknownLabel) } /** This factory adds a decoupled handshaking protocol to a data bundle. */ object Decoupled { /** Wraps some Data with a DecoupledIO interface. */ - def apply[T <: Data](gen: T): DecoupledIO[T] = new DecoupledIO(gen) + def apply[T <: Data](gen: T, rdyl: Label = UnknownLabel, vall: Label = UnknownLabel): DecoupledIO[T] = new DecoupledIO(gen, rdyl, vall) /** Downconverts an IrrevocableIO output to a DecoupledIO, dropping guarantees of irrevocability. * @@ -93,9 +111,6 @@ object Decoupled irr.ready := d.ready d } -// override def cloneType: this.type = { -// DeqIO(gen).asInstanceOf[this.type] -// } } /** A concrete subclass of ReadyValidIO that promises to not change @@ -170,8 +185,6 @@ class Queue[T <: Data](gen: T, flow: Boolean = false, override_reset: Option[Bool] = None) extends Module(override_reset=override_reset) { - def this(gen: T, entries: Int, pipe: Boolean, flow: Boolean, _reset: Bool) = - this(gen, entries, pipe, flow, Some(_reset)) val io = IO(new QueueIO(gen, entries)) @@ -186,6 +199,7 @@ extends Module(override_reset=override_reset) { private val do_enq = Wire(init=io.enq.fire()) private val do_deq = Wire(init=io.deq.fire()) + when (do_enq) { ram(enq_ptr.value) := io.enq.bits enq_ptr.inc() diff --git a/src/main/scala/chisel3/util/Valid.scala b/src/main/scala/chisel3/util/Valid.scala index 0229b7f..bb907af 100644 --- a/src/main/scala/chisel3/util/Valid.scala +++ b/src/main/scala/chisel3/util/Valid.scala @@ -1,7 +1,7 @@ // See LICENSE for license details. /** Wrappers for valid interfaces and associated circuit generators using them. - */ + */ package chisel3.util @@ -9,52 +9,102 @@ import chisel3._ // TODO: remove this once we have CompileOptions threaded through the macro system. import chisel3.core.ExplicitCompileOptions.NotStrict +import chisel3.core.{HLevel, VLabel} +import chisel3.internal.firrtl.{Node} + /** An Bundle containing data and a signal determining if it is valid */ -class Valid[+T <: Data](gen: T) extends Bundle +class Valid[+T <: Data](gen: T, val vall: Label=UnknownLabel, val genl: Label=UnknownLabel) extends Bundle { - val valid = Output(Bool()) - val bits = Output(gen.chiselCloneType) + val valid = Output(Bool(), vall) + val bits = genl match { + case UnknownLabel => Output(gen.chiselCloneType) + case _ => Output(gen.chiselCloneType, genl) + } def fire(dummy: Int = 0): Bool = valid - override def cloneType: this.type = Valid(gen).asInstanceOf[this.type] + override def cloneType: this.type = Valid(gen, vall).asInstanceOf[this.type] + override def _onModuleClose: Unit = { + super._onModuleClose + bits match { + case bx: Record => + if(valid.lbl != null) { + valid.lbl.conf match { + case lx: HLevel => + if(argIsTemp(lx.id.getRef) && (bx.elements contains lx.id.getRef.name)) { + lx.id.setRef(bx, lx.id.getRef.name) + // println("valid hlvl ref: " + lx.id.getRef.pprint) + // println(s"this: ${this.getRef.pprint}") + // println(s"bx: ${bx.getRef.pprint}") + + // //lx.id.setRef(swapTmpWithId(lx.id.getRef, this)) + // val slots = slotsToNames(lx.id.getRef) + // val elt = bx.namesToElt(slots) + // println(s"slots: ${slots.toString}") + // println(s"elt: ${elt.toString}") + // println(s"eltId: ${elt.getRef.pprint}") + // lx.id.setRef(Node(elt)) + // lx.id.setRef(bx, lots) + // println (s"slots pretty: ${lx.id.getRef.pprint}") + // if(bx.elements contains lx.id.getRef.name) lx.id.setRef(bx, lx.id.getRef.name) + } + case lx: VLabel => + if(argIsTemp(lx.id.getRef) && (bx.elements contains lx.id.getRef.name)) + lx.id.setRef(bx, lx.id.getRef.name) + case lx => + } + valid.lbl.integ match { + case lx: HLevel => + if(argIsTemp(lx.id.getRef) && (bx.elements contains lx.id.getRef.name)) + lx.id.setRef(bx, lx.id.getRef.name) + case lx: VLabel => + if(argIsTemp(lx.id.getRef) && (bx.elements contains lx.id.getRef.name)) + lx.id.setRef(bx, lx.id.getRef.name) + case lx => + } + } + case _ => + } + } } /** Adds a valid protocol to any interface */ object Valid { - def apply[T <: Data](gen: T): Valid[T] = new Valid(gen) + def apply[T <: Data](gen: T, vall: Label=UnknownLabel, genl: Label=UnknownLabel): Valid[T] = new Valid(gen, vall, genl) } /** A hardware module that delays data coming down the pipeline - by the number of cycles set by the latency parameter. Functionality - is similar to ShiftRegister but this exposes a Pipe interface. - - Example usage: - val pipe = new Pipe(UInt()) - pipe.io.enq <> produce.io.out - consumer.io.in <> pipe.io.deq - */ + by the number of cycles set by the latency parameter. Functionality + is similar to ShiftRegister but this exposes a Pipe interface. + + Example usage: + val pipe = new Pipe(UInt()) + pipe.io.enq <> produce.io.out + consumer.io.in <> pipe.io.deq + */ object Pipe { - def apply[T <: Data](enqValid: Bool, enqBits: T, latency: Int): Valid[T] = { + def apply[T <: Data](enqValid: Bool, enqBits: T, latency: Int, pvall: Label, pgenl: Label): Valid[T] = { if (latency == 0) { - val out = Wire(Valid(enqBits)) + val out = Wire(Valid(enqBits, vall=pvall, genl=pgenl)) out.valid <> enqValid out.bits <> enqBits out } else { val v = Reg(Bool(), next=enqValid, init=false.B) val b = RegEnable(enqBits, enqValid) - apply(v, b, latency-1) + apply(v, b, latency-1, pvall, pgenl) } } - def apply[T <: Data](enqValid: Bool, enqBits: T): Valid[T] = apply(enqValid, enqBits, 1) - def apply[T <: Data](enq: Valid[T], latency: Int = 1): Valid[T] = apply(enq.valid, enq.bits, latency) + def apply[T <: Data](enqValid: Bool, enqBits: T): Valid[T] = apply(enqValid, enqBits, 1, UnknownLabel, UnknownLabel) + def apply[T <: Data](enqValid: Bool, enqBits: T, latency: Int): Valid[T] = apply(enqValid, enqBits, latency, UnknownLabel, UnknownLabel) + def apply[T <: Data](enq: Valid[T], latency: Int = 1, pvall: Label = UnknownLabel, pgenl: Label=UnknownLabel): Valid[T] = apply(enq.valid, enq.bits, latency, pvall, pgenl) + //def apply[T <: Data](enq: Valid[T], latency: Int= 1, pvall: Label, pgenl: Label): Valid[T] = apply(enq.valid, enq.bits, latency, pvall, pgenl) } -class Pipe[T <: Data](gen: T, latency: Int = 1) extends Module +class Pipe[T <: Data](gen: T, latency: Int = 1, pvall: Label=UnknownLabel, pgenl: Label=UnknownLabel) extends Module { class PipeIO extends Bundle { - val enq = Input(Valid(gen)) - val deq = Output(Valid(gen)) + val enq = Input(Valid(gen, pvall, pgenl)) + val deq = Output(Valid(gen, pvall, pgenl)) } val io = IO(new PipeIO)