summaryrefslogtreecommitdiff
path: root/chiselFrontend/src/main/scala/chisel3/internal/firrtl
diff options
context:
space:
mode:
authorJack Koenig2020-03-22 18:13:58 -0700
committerJack Koenig2020-03-25 19:17:15 -0700
commitfbf5e6f1a0e8bf535d465b748ad554575fe62156 (patch)
tree578858ab6d219ca6daf44cf87b73f75054989097 /chiselFrontend/src/main/scala/chisel3/internal/firrtl
parentb2e004fb615a3c931d910a338b9faa99c1c975d7 (diff)
Rename subprojects to more canonical names
* Rename coreMacros to macros * Rename chiselFrontend to core Also make each subproject publish with "chisel3-" as a prefix
Diffstat (limited to 'chiselFrontend/src/main/scala/chisel3/internal/firrtl')
-rw-r--r--chiselFrontend/src/main/scala/chisel3/internal/firrtl/Converter.scala275
-rw-r--r--chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala750
2 files changed, 0 insertions, 1025 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/Converter.scala b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/Converter.scala
deleted file mode 100644
index 5c1d6935..00000000
--- a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/Converter.scala
+++ /dev/null
@@ -1,275 +0,0 @@
-// See LICENSE for license details.
-
-package chisel3.internal.firrtl
-import chisel3._
-import chisel3.experimental._
-import chisel3.internal.sourceinfo.{NoSourceInfo, SourceLine, SourceInfo}
-import firrtl.{ir => fir}
-import chisel3.internal.{castToInt, throwException}
-
-import scala.annotation.tailrec
-import scala.collection.immutable.Queue
-
-private[chisel3] object Converter {
- // TODO modeled on unpack method on Printable, refactor?
- def unpack(pable: Printable, ctx: Component): (String, Seq[Arg]) = pable match {
- case Printables(pables) =>
- val (fmts, args) = pables.map(p => unpack(p, ctx)).unzip
- (fmts.mkString, args.flatten.toSeq)
- 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 FullName(data) => (data.ref.fullName(ctx), List.empty)
- case Percent => ("%%", List.empty)
- }
-
- def convert(info: SourceInfo): fir.Info = info match {
- case _: NoSourceInfo => fir.NoInfo
- case SourceLine(fn, line, col) => fir.FileInfo(fir.StringLit(s"$fn $line:$col"))
- }
-
- def convert(op: PrimOp): fir.PrimOp = firrtl.PrimOps.fromString(op.name)
-
- def convert(dir: MemPortDirection): firrtl.MPortDir = dir match {
- case MemPortDirection.INFER => firrtl.MInfer
- case MemPortDirection.READ => firrtl.MRead
- case MemPortDirection.WRITE => firrtl.MWrite
- case MemPortDirection.RDWR => firrtl.MReadWrite
- }
-
- // TODO
- // * Memoize?
- // * Move into the Chisel IR?
- def convert(arg: Arg, ctx: Component): fir.Expression = arg match { // scalastyle:ignore cyclomatic.complexity
- case Node(id) =>
- convert(id.getRef, ctx)
- case Ref(name) =>
- fir.Reference(name, fir.UnknownType)
- case Slot(imm, name) =>
- fir.SubField(convert(imm, ctx), name, fir.UnknownType)
- case Index(imm, ILit(idx)) =>
- fir.SubIndex(convert(imm, ctx), castToInt(idx, "Index"), fir.UnknownType)
- case Index(imm, value) =>
- fir.SubAccess(convert(imm, ctx), convert(value, ctx), fir.UnknownType)
- case ModuleIO(mod, name) =>
- // scalastyle:off if.brace
- if (mod eq ctx.id) fir.Reference(name, fir.UnknownType)
- else fir.SubField(fir.Reference(mod.getRef.name, fir.UnknownType), name, fir.UnknownType)
- // scalastyle:on if.brace
- case u @ ULit(n, UnknownWidth()) =>
- 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))
- val unsigned = if (n < 0) (BigInt(1) << slit.width.get) + n else n
- val uint = convert(ULit(unsigned, slit.width), ctx)
- fir.DoPrim(firrtl.PrimOps.AsSInt, Seq(uint), Seq.empty, fir.UnknownType)
- // TODO Simplify
- case fplit @ FPLit(n, w, bp) =>
- val unsigned = if (n < 0) (BigInt(1) << fplit.width.get) + n else n
- val uint = convert(ULit(unsigned, fplit.width), ctx)
- val lit = bp.asInstanceOf[KnownBinaryPoint].value
- fir.DoPrim(firrtl.PrimOps.AsFixedPoint, Seq(uint), Seq(lit), fir.UnknownType)
- case intervalLit @ IntervalLit(n, w, bp) =>
- val unsigned = if (n < 0) (BigInt(1) << intervalLit.width.get) + n else n
- val uint = convert(ULit(unsigned, intervalLit.width), ctx)
- val lit = bp.asInstanceOf[KnownBinaryPoint].value
- fir.DoPrim(firrtl.PrimOps.AsInterval, Seq(uint), Seq(n, n, lit), fir.UnknownType)
- case lit: ILit =>
- throwException(s"Internal Error! Unexpected ILit: $lit")
- }
-
- /** Convert Commands that map 1:1 to Statements */
- def convertSimpleCommand(cmd: Command, ctx: Component): Option[fir.Statement] = cmd match { // scalastyle:ignore cyclomatic.complexity line.size.limit
- case e: DefPrim[_] =>
- val consts = e.args.collect { case ILit(i) => i }
- val args = e.args.flatMap {
- case _: ILit => None
- case other => Some(convert(other, ctx))
- }
- val expr = e.op.name match {
- case "mux" =>
- assert(args.size == 3, s"Mux with unexpected args: $args")
- fir.Mux(args(0), args(1), args(2), fir.UnknownType)
- case _ =>
- fir.DoPrim(convert(e.op), args, consts, fir.UnknownType)
- }
- Some(fir.DefNode(convert(e.sourceInfo), e.name, expr))
- case e @ DefWire(info, id) =>
- Some(fir.DefWire(convert(info), e.name, extractType(id)))
- case e @ DefReg(info, id, clock) =>
- Some(fir.DefRegister(convert(info), e.name, extractType(id), convert(clock, ctx),
- firrtl.Utils.zero, convert(id.getRef, ctx)))
- case e @ DefRegInit(info, id, clock, reset, init) =>
- Some(fir.DefRegister(convert(info), e.name, extractType(id), convert(clock, ctx),
- convert(reset, ctx), convert(init, ctx)))
- case e @ DefMemory(info, id, t, size) =>
- Some(firrtl.CDefMemory(convert(info), e.name, extractType(t), size, false))
- case e @ DefSeqMemory(info, id, t, size, ruw) =>
- Some(firrtl.CDefMemory(convert(info), e.name, extractType(t), size, true, ruw))
- case e: DefMemPort[_] =>
- Some(firrtl.CDefMPort(convert(e.sourceInfo), e.name, fir.UnknownType,
- e.source.fullName(ctx), Seq(convert(e.index, ctx), convert(e.clock, ctx)), convert(e.dir)))
- case Connect(info, loc, exp) =>
- Some(fir.Connect(convert(info), convert(loc, ctx), convert(exp, ctx)))
- case BulkConnect(info, loc, exp) =>
- Some(fir.PartialConnect(convert(info), convert(loc, ctx), convert(exp, ctx)))
- case Attach(info, locs) =>
- Some(fir.Attach(convert(info), locs.map(l => convert(l, ctx))))
- case DefInvalid(info, arg) =>
- Some(fir.IsInvalid(convert(info), convert(arg, ctx)))
- case e @ DefInstance(info, id, _) =>
- Some(fir.DefInstance(convert(info), e.name, id.name))
- case Stop(info, clock, ret) =>
- Some(fir.Stop(convert(info), ret, convert(clock, ctx), firrtl.Utils.one))
- case Printf(info, clock, pable) =>
- val (fmt, args) = unpack(pable, ctx)
- Some(fir.Print(convert(info), fir.StringLit(fmt),
- args.map(a => convert(a, ctx)), convert(clock, ctx), firrtl.Utils.one))
- case _ => None
- }
-
- /** Internal datastructure to help translate Chisel's flat Command structure to FIRRTL's AST
- *
- * In particular, when scoping is translated from flat with begin end to a nested datastructure
- *
- * @param when Current when Statement, holds info, condition, and consequence as they are
- * available
- * @param outer Already converted Statements that precede the current when block in the scope in
- * which the when is defined (ie. 1 level up from the scope inside the when)
- * @param alt Indicates if currently processing commands in the alternate (else) of the when scope
- */
- // TODO we should probably have a different structure in the IR to close elses
- private case class WhenFrame(when: fir.Conditionally, outer: Queue[fir.Statement], alt: Boolean)
-
- /** Convert Chisel IR Commands into FIRRTL Statements
- *
- * @note ctx is needed because references to ports translate differently when referenced within
- * the module in which they are defined vs. parent modules
- * @param cmds Chisel IR Commands to convert
- * @param ctx Component (Module) context within which we are translating
- * @return FIRRTL Statement that is equivalent to the input cmds
- */
- def convert(cmds: Seq[Command], ctx: Component): fir.Statement = { // scalastyle:ignore cyclomatic.complexity
- @tailrec
- // scalastyle:off if.brace
- 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), 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)
- }
- }
- }
- // scalastyle:on if.brace
- fir.Block(rec(Queue.empty, List.empty)(cmds))
- }
-
- def convert(width: Width): fir.Width = width match {
- case UnknownWidth() => fir.UnknownWidth
- case KnownWidth(value) => fir.IntWidth(value)
- }
-
- def convert(bp: BinaryPoint): fir.Width = bp match {
- case UnknownBinaryPoint => fir.UnknownWidth
- case KnownBinaryPoint(value) => fir.IntWidth(value)
- }
-
- private def firrtlUserDirOf(d: Data): SpecifiedDirection = d match {
- case d: Vec[_] =>
- SpecifiedDirection.fromParent(d.specifiedDirection, firrtlUserDirOf(d.sample_element))
- case d => d.specifiedDirection
- }
-
- def extractType(data: Data, clearDir: Boolean = false): fir.Type = data match { // scalastyle:ignore cyclomatic.complexity line.size.limit
- 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 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: Vec[_] => fir.VectorType(extractType(d.sample_element, clearDir), d.length)
- case d: Record =>
- val childClearDir = clearDir ||
- d.specifiedDirection == SpecifiedDirection.Input || d.specifiedDirection == SpecifiedDirection.Output
- def eltField(elt: Data): fir.Field = (childClearDir, firrtlUserDirOf(elt)) match {
- case (true, _) => fir.Field(elt.getRef.name, fir.Default, extractType(elt, true))
- case (false, SpecifiedDirection.Unspecified | SpecifiedDirection.Output) =>
- fir.Field(elt.getRef.name, fir.Default, extractType(elt, false))
- case (false, SpecifiedDirection.Flip | SpecifiedDirection.Input) =>
- fir.Field(elt.getRef.name, fir.Flip, extractType(elt, false))
- }
- 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 DoubleParam(value) => fir.DoubleParam(name, value)
- case StringParam(value) => fir.StringParam(name, fir.StringLit(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
- }
- val clearDir = resolvedDir match {
- case SpecifiedDirection.Input | SpecifiedDirection.Output => true
- case SpecifiedDirection.Unspecified | SpecifiedDirection.Flip => false
- }
- val tpe = extractType(port.id, clearDir)
- fir.Port(fir.NoInfo, port.id.getRef.name, dir, tpe)
- }
-
- def convert(component: Component): fir.DefModule = component match {
- 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)
- }
-
- def convert(circuit: Circuit): fir.Circuit =
- fir.Circuit(fir.NoInfo, circuit.components.map(convert), circuit.name)
-}
-
diff --git a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala
deleted file mode 100644
index d98bebcd..00000000
--- a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala
+++ /dev/null
@@ -1,750 +0,0 @@
-// See LICENSE for license details.
-
-package chisel3.internal.firrtl
-
-import firrtl.{ir => fir}
-
-import chisel3._
-import chisel3.internal._
-import chisel3.internal.sourceinfo.SourceInfo
-import chisel3.experimental._
-import _root_.firrtl.{ir => firrtlir}
-import _root_.firrtl.PrimOps
-
-import scala.collection.immutable.NumericRange
-import scala.math.BigDecimal.RoundingMode
-
-// scalastyle:off number.of.types
-
-case class PrimOp(name: String) {
- override def toString: String = name
-}
-
-object PrimOp {
- val AddOp = PrimOp("add")
- val SubOp = PrimOp("sub")
- val TailOp = PrimOp("tail")
- val HeadOp = PrimOp("head")
- val TimesOp = PrimOp("mul")
- val DivideOp = PrimOp("div")
- val RemOp = PrimOp("rem")
- val ShiftLeftOp = PrimOp("shl")
- val ShiftRightOp = PrimOp("shr")
- val DynamicShiftLeftOp = PrimOp("dshl")
- val DynamicShiftRightOp = PrimOp("dshr")
- val BitAndOp = PrimOp("and")
- val BitOrOp = PrimOp("or")
- val BitXorOp = PrimOp("xor")
- val BitNotOp = PrimOp("not")
- val ConcatOp = PrimOp("cat")
- val BitsExtractOp = PrimOp("bits")
- val LessOp = PrimOp("lt")
- val LessEqOp = PrimOp("leq")
- val GreaterOp = PrimOp("gt")
- val GreaterEqOp = PrimOp("geq")
- val EqualOp = PrimOp("eq")
- val PadOp = PrimOp("pad")
- val NotEqualOp = PrimOp("neq")
- val NegOp = PrimOp("neg")
- val MultiplexOp = PrimOp("mux")
- val AndReduceOp = PrimOp("andr")
- val OrReduceOp = PrimOp("orr")
- val XorReduceOp = PrimOp("xorr")
- val ConvertOp = PrimOp("cvt")
- val AsUIntOp = PrimOp("asUInt")
- val AsSIntOp = PrimOp("asSInt")
- val AsFixedPointOp = PrimOp("asFixedPoint")
- val AsIntervalOp = PrimOp("asInterval")
- val WrapOp = PrimOp("wrap")
- val SqueezeOp = PrimOp("squz")
- val ClipOp = PrimOp("clip")
- val SetBinaryPoint = PrimOp("setp")
- val IncreasePrecision = PrimOp("incp")
- val DecreasePrecision = PrimOp("decp")
- val AsClockOp = PrimOp("asClock")
- val AsAsyncResetOp = PrimOp("asAsyncReset")
-}
-
-abstract class Arg {
- def fullName(ctx: Component): String = name
- def name: String
-}
-
-case class Node(id: HasId) extends Arg {
- override def fullName(ctx: Component): String = id.getOptionRef match {
- case Some(arg) => arg.fullName(ctx)
- case None => id.suggestedName.getOrElse("??")
- }
- def name: String = id.getOptionRef match {
- case Some(arg) => arg.name
- case None => id.suggestedName.getOrElse("??")
- }
-}
-
-abstract class LitArg(val num: BigInt, widthArg: Width) extends Arg {
- private[chisel3] def forcedWidth = widthArg.known
- private[chisel3] def width: Width = if (forcedWidth) widthArg else Width(minWidth)
- override def fullName(ctx: Component): String = name
- // Ensure the node representing this LitArg has a ref to it and a literal binding.
- def bindLitArg[T <: Element](elem: T): T = {
- elem.bind(ElementLitBinding(this))
- elem.setRef(this)
- elem
- }
-
- 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.") // scalastyle:ignore line.size.limit
- }
-}
-
-case class ILit(n: BigInt) extends Arg {
- def name: String = n.toString
-}
-
-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
-
- require(n >= 0, s"UInt literal ${n} is negative")
-}
-
-case class SLit(n: BigInt, w: Width) extends LitArg(n, w) {
- def name: String = {
- val unsigned = if (n < 0) (BigInt(1) << width.get) + n else n
- s"asSInt(${ULit(unsigned, width).name})"
- }
- def minWidth: Int = 1 + n.bitLength
-}
-
-case class FPLit(n: BigInt, w: Width, binaryPoint: BinaryPoint) extends LitArg(n, w) {
- def name: String = {
- val unsigned = if (n < 0) (BigInt(1) << width.get) + n else n
- s"asFixedPoint(${ULit(unsigned, width).name}, ${binaryPoint.asInstanceOf[KnownBinaryPoint].value})"
- }
- def minWidth: Int = 1 + n.bitLength
-}
-
-case class IntervalLit(n: BigInt, w: Width, binaryPoint: BinaryPoint) extends LitArg(n, w) {
- def name: String = {
- val unsigned = if (n < 0) (BigInt(1) << width.get) + n else n
- 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))
- }
- def minWidth: Int = 1 + n.bitLength
-}
-
-case class Ref(name: String) extends Arg
-case class ModuleIO(mod: BaseModule, name: String) extends Arg {
- override def fullName(ctx: Component): String =
- if (mod eq ctx.id) name else s"${mod.getRef.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}"
-}
-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)}]"
-}
-
-object Width {
- def apply(x: Int): Width = KnownWidth(x)
- def apply(): Width = UnknownWidth()
-}
-
-sealed abstract class Width {
- type W = Int
- 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
- 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 op(that: Width, f: (W, W) => W): Width = this
- override def toString: String = ""
-}
-
-sealed case class KnownWidth(value: Int) extends Width {
- require(value >= 0)
- def known: Boolean = true
- def get: Int = value
- def op(that: Width, f: (W, W) => W): Width = that match {
- case KnownWidth(x) => KnownWidth(f(value, x))
- case _ => that
- }
- override def toString: String = s"<${value.toString}>"
-}
-
-object BinaryPoint {
- def apply(x: Int): BinaryPoint = KnownBinaryPoint(x)
- def apply(): BinaryPoint = UnknownBinaryPoint
-}
-
-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 dynamicShiftLeft(that: BinaryPoint): BinaryPoint =
- this.op(that, (a, b) => a + (1 << b) - 1)
-
- def known: Boolean
- 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 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 op(that: BinaryPoint, f: (W, W) => W): BinaryPoint = that match {
- case KnownBinaryPoint(x) => KnownBinaryPoint(f(value, x))
- case _ => that
- }
- override def toString: String = s"<<${value.toString}>>"
-}
-
-
-sealed abstract class MemPortDirection(name: String) {
- override def toString: String = name
-}
-object MemPortDirection {
- object READ extends MemPortDirection("read")
- object WRITE extends MemPortDirection("write")
- object RDWR extends MemPortDirection("rdwr")
- object INFER extends MemPortDirection("infer")
-}
-
-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 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
- * @param firrtlBinaryPoint binary point firrtl style
- * @return
- */
- def apply(lower: firrtlir.Bound, upper: firrtlir.Bound, firrtlBinaryPoint: firrtlir.Width): IntervalRange = {
- new IntervalRange(lower, upper, firrtlBinaryPoint)
- }
-
- def apply(lower: firrtlir.Bound, upper: firrtlir.Bound, binaryPoint: BinaryPoint): IntervalRange = {
- new IntervalRange(lower, upper, IntervalRange.getBinaryPoint(binaryPoint))
- }
-
- def apply(lower: firrtlir.Bound, upper: firrtlir.Bound, binaryPoint: Int): IntervalRange = {
- IntervalRange(lower, upper, BinaryPoint(binaryPoint))
- }
-
- /** Returns an IntervalRange appropriate for a signed value of the given width
- * @param binaryPoint number of bits of mantissa
- * @return
- */
- def apply(binaryPoint: BinaryPoint): IntervalRange = {
- IntervalRange(firrtlir.UnknownBound, firrtlir.UnknownBound, binaryPoint)
- }
-
- /** Returns an IntervalRange appropriate for a signed value of the given width
- * @param width number of bits to have in the interval
- * @param binaryPoint number of bits of mantissa
- * @return
- */
- def apply(width: Width, binaryPoint: BinaryPoint = 0.BP): IntervalRange = {
- val range = width match {
- case KnownWidth(w) =>
- val nearestPowerOf2 = BigInt("1" + ("0" * (w - 1)), 2)
- IntervalRange(
- firrtlir.Closed(BigDecimal(-nearestPowerOf2)), firrtlir.Closed(BigDecimal(nearestPowerOf2 - 1)), binaryPoint
- )
- case _ =>
- IntervalRange(firrtlir.UnknownBound, firrtlir.UnknownBound, binaryPoint)
- }
- range
- }
-
- def unapply(arg: IntervalRange): Option[(firrtlir.Bound, firrtlir.Bound, BinaryPoint)] = {
- return Some((arg.lower, arg.upper, arg.binaryPoint))
- }
-
- def getBound(isClosed: Boolean, value: String): firrtlir.Bound = {
- if(value == "?") {
- firrtlir.UnknownBound
- }
- else if(isClosed) {
- firrtlir.Closed(BigDecimal(value))
- }
- else {
- firrtlir.Open(BigDecimal(value))
- }
- }
-
- def getBound(isClosed: Boolean, value: BigDecimal): firrtlir.Bound = {
- if(isClosed) {
- firrtlir.Closed(value)
- }
- else {
- firrtlir.Open(value)
- }
- }
-
- def getBound(isClosed: Boolean, value: Int): firrtlir.Bound = {
- getBound(isClosed, (BigDecimal(value)))
- }
-
- def getBinaryPoint(s: String): firrtlir.Width = {
- firrtlir.UnknownWidth
- }
-
- def getBinaryPoint(n: Int): firrtlir.Width = {
- if(n < 0) {
- firrtlir.UnknownWidth
- }
- else {
- firrtlir.IntWidth(n)
- }
- }
- def getBinaryPoint(n: BinaryPoint): firrtlir.Width = {
- n match {
- case UnknownBinaryPoint => firrtlir.UnknownWidth
- case KnownBinaryPoint(w) => firrtlir.IntWidth(w)
- }
- }
-
- def getRangeWidth(w: Width): firrtlir.Width = {
- if(w.known) {
- firrtlir.IntWidth(w.get)
- }
- else {
- firrtlir.UnknownWidth
- }
- }
- def getRangeWidth(binaryPoint: BinaryPoint): firrtlir.Width = {
- if(binaryPoint.known) {
- firrtlir.IntWidth(binaryPoint.get)
- }
- else {
- firrtlir.UnknownWidth
- }
- }
-
- //scalastyle:off method.name
- 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)
- with RangeType {
-
- (lowerBound, upperBound) match {
- case (firrtlir.Open(begin), firrtlir.Open(end)) =>
- 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))) {
- 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}")
- case (firrtlir.Closed(begin), firrtlir.Open(end)) =>
- 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}")
- case _ =>
- }
-
- //scalastyle:off cyclomatic.complexity
- override def toString: String = {
- val binaryPoint = firrtlBinaryPoint match {
- case firrtlir.IntWidth(n) => s"$n"
- case _ => "?"
- }
- val lowerBoundString = lowerBound match {
- 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"?]"
- }
- s"""range"$lowerBoundString,$upperBoundString.$binaryPoint""""
- }
-
- val increment: Option[BigDecimal] = firrtlBinaryPoint match {
- case firrtlir.IntWidth(bp) =>
- Some(BigDecimal(math.pow(2, -bp.doubleValue)))
- case _ => None
- }
-
- /** If possible returns the lowest possible value for this Interval
- * @return
- */
- val getLowestPossibleValue: Option[BigDecimal] = {
- increment match {
- case Some(inc) =>
- lower match {
- case firrtlir.Closed(n) => Some(n)
- case firrtlir.Open(n) => Some(n + inc)
- case _ => None
- }
- case _ =>
- None
- }
- }
-
- /** If possible returns the highest possible value for this Interval
- * @return
- */
- val getHighestPossibleValue: Option[BigDecimal] = {
- increment match {
- case Some(inc) =>
- upper match {
- case firrtlir.Closed(n) => Some(n)
- case firrtlir.Open(n) => Some(n - inc)
- case _ => None
- }
- case _ =>
- None
- }
- }
-
- /** Return a Seq of the possible values for this range
- * Mostly to be used for testing
- * @return
- */
- def getPossibleValues: NumericRange[BigDecimal] = {
- (getLowestPossibleValue, getHighestPossibleValue, increment) match {
- case (Some(low), Some(high), Some(inc)) => (low to high by inc)
- case (_, _, None) =>
- throw new ChiselException(s"BinaryPoint unknown. Cannot get possible values from IntervalRange $toString")
- case _ =>
- throw new ChiselException(s"Unknown Bound. Cannot get possible values from IntervalRange $toString")
-
- }
- }
-
- override def getWidth: Width = {
- width match {
- 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 {
- case i: firrtlir.IntervalType => IntervalRange(i.lower, i.upper, i.point)
- case other => sys.error("BAD!")
- }
- }
-
- private def doFirrtlDynamicShift(that: UInt, isLeft: Boolean): IntervalRange = {
- val uinttpe = that.widthOption match {
- 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 {
- 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 {
- case i: firrtlir.IntervalType => IntervalRange(i.lower, i.upper, i.point)
- case other => sys.error("BAD!")
- }
- }
-
- /** Multiply this by that, here we return a fully unknown range,
- * firrtl's range inference can figure this out
- * @param that
- * @return
- */
- override def *(that: IntervalRange): IntervalRange = {
- doFirrtlOp(PrimOps.Mul, that)
- }
-
- /** Add that to this, here we return a fully unknown range,
- * firrtl's range inference can figure this out
- * @param that
- * @return
- */
- override def +&(that: IntervalRange): IntervalRange = {
- doFirrtlOp(PrimOps.Add, that)
- }
-
- /** Subtract that from this, here we return a fully unknown range,
- * firrtl's range inference can figure this out
- * @param that
- * @return
- */
- override def -&(that: IntervalRange): IntervalRange = {
- doFirrtlOp(PrimOps.Sub, that)
- }
-
- private def adjustBoundValue(value: BigDecimal, binaryPointValue: Int): BigDecimal = {
- if(binaryPointValue >= 0) {
- val maskFactor = BigDecimal(1 << binaryPointValue)
- val a = (value * maskFactor)
- val b = a.setScale(0, RoundingMode.DOWN)
- val c = b / maskFactor
- c
- } else {
- value
- }
- }
-
- private def adjustBound(bound: firrtlir.Bound, binaryPoint: BinaryPoint): firrtlir.Bound = {
- binaryPoint match {
- case KnownBinaryPoint(binaryPointValue) =>
- bound match {
- case firrtlir.Open(value) => firrtlir.Open(adjustBoundValue(value, binaryPointValue))
- case firrtlir.Closed(value) => firrtlir.Closed(adjustBoundValue(value, binaryPointValue))
- case _ => bound
- }
- case _ => firrtlir.UnknownBound
- }
- }
-
- /** Creates a new range with the increased precision
- *
- * @param newBinaryPoint
- * @return
- */
- def incPrecision(newBinaryPoint: BinaryPoint): IntervalRange = {
- newBinaryPoint match {
- case KnownBinaryPoint(that) =>
- doFirrtlOp(PrimOps.IncP, that)
- case _ =>
- throwException(s"$this.incPrecision(newBinaryPoint = $newBinaryPoint) error, newBinaryPoint must be know")
- }
- }
-
- /** Creates a new range with the decreased precision
- *
- * @param newBinaryPoint
- * @return
- */
- def decPrecision(newBinaryPoint: BinaryPoint): IntervalRange = {
- newBinaryPoint match {
- case KnownBinaryPoint(that) =>
- doFirrtlOp(PrimOps.DecP, that)
- case _ =>
- throwException(s"$this.decPrecision(newBinaryPoint = $newBinaryPoint) error, newBinaryPoint must be know")
- }
- }
-
- /** Creates a new range with the given binary point, adjusting precision
- * on bounds as necessary
- *
- * @param newBinaryPoint
- * @return
- */
- def setPrecision(newBinaryPoint: BinaryPoint): IntervalRange = {
- newBinaryPoint match {
- case KnownBinaryPoint(that) =>
- doFirrtlOp(PrimOps.SetP, that)
- case _ =>
- throwException(s"$this.setPrecision(newBinaryPoint = $newBinaryPoint) error, newBinaryPoint must be know")
- }
- }
-
- /** Shift this range left, i.e. shifts the min and max by the specified amount
- * @param that
- * @return
- */
- override def <<(that: Int): IntervalRange = {
- doFirrtlOp(PrimOps.Shl, that)
- }
-
- /** Shift this range left, i.e. shifts the min and max by the known width
- * @param that
- * @return
- */
- override def <<(that: KnownWidth): IntervalRange = {
- <<(that.value)
- }
-
- /** Shift this range left, i.e. shifts the min and max by value
- * @param that
- * @return
- */
- def <<(that: UInt): IntervalRange = {
- doFirrtlDynamicShift(that, isLeft = true)
- }
-
- /** Shift this range right, i.e. shifts the min and max by the specified amount
- * @param that
- * @return
- */
- override def >>(that: Int): IntervalRange = {
- doFirrtlOp(PrimOps.Shr, that)
- }
-
- /** Shift this range right, i.e. shifts the min and max by the known width
- * @param that
- * @return
- */
- override def >>(that: KnownWidth): IntervalRange = {
- >>(that.value)
- }
-
- /** Shift this range right, i.e. shifts the min and max by value
- * @param that
- * @return
- */
- def >>(that: UInt): IntervalRange = {
- doFirrtlDynamicShift(that, isLeft = false)
- }
-
- /**
- * Squeeze returns the intersection of the ranges this interval and that Interval
- * @param that
- * @return
- */
- def squeeze(that: IntervalRange): IntervalRange = {
- doFirrtlOp(PrimOps.Squeeze, that)
- }
-
- /**
- * Wrap the value of this [[Interval]] into the range of a different Interval with a presumably smaller range.
- * @param that
- * @return
- */
- def wrap(that: IntervalRange): IntervalRange = {
- doFirrtlOp(PrimOps.Wrap, that)
- }
-
- /**
- * Clip the value of this [[Interval]] into the range of a different Interval with a presumably smaller range.
- * @param that
- * @return
- */
- def clip(that: IntervalRange): IntervalRange = {
- doFirrtlOp(PrimOps.Clip, that)
- }
-
- /** merges the ranges of this and that, basically takes lowest low, highest high and biggest bp
- * set unknown if any of this or that's value of above is unknown
- * Like an union but will slurp up points in between the two ranges that were part of neither
- * @param that
- * @return
- */
- 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 }
- case _ =>
- firrtlir.UnknownBound
- }
- val highest = (this.getHighestPossibleValue, that.getHighestPossibleValue) match {
- case (Some(l1), Some(l2)) =>
- 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) }
- case _ =>
- firrtlir.UnknownWidth
- }
- IntervalRange(lowest, highest, newBinaryPoint)
- }
-
- def binaryPoint: BinaryPoint = {
- firrtlBinaryPoint match {
- case firrtlir.IntWidth(n) =>
- assert(n < Int.MaxValue, s"binary point value $n is out of range")
- KnownBinaryPoint(n.toInt)
- case _ => UnknownBinaryPoint
- }
- }
-}
-
-abstract class Command {
- def sourceInfo: SourceInfo
-}
-abstract class Definition extends Command {
- def id: HasId
- def name: String = id.getRef.name
-}
-// scalastyle:off line.size.limit
-case class DefPrim[T <: Data](sourceInfo: SourceInfo, id: T, op: PrimOp, args: Arg*) extends Definition
-case class DefInvalid(sourceInfo: SourceInfo, arg: Arg) extends Command
-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 DefInstance(sourceInfo: SourceInfo, id: BaseModule, ports: Seq[Port]) extends Definition
-case class WhenBegin(sourceInfo: SourceInfo, pred: Arg) extends Command
-case class WhenEnd(sourceInfo: SourceInfo, firrtlDepth: Int, hasAlt: Boolean = false) extends Command
-case class AltBegin(sourceInfo: SourceInfo) extends Command
-case class OtherwiseEnd(sourceInfo: SourceInfo, firrtlDepth: Int) extends Command
-case class Connect(sourceInfo: SourceInfo, loc: Node, exp: Arg) extends Command
-case class BulkConnect(sourceInfo: SourceInfo, loc1: Node, loc2: Node) extends Command
-case class Attach(sourceInfo: SourceInfo, locs: Seq[Node]) extends Command
-case class ConnectInit(sourceInfo: SourceInfo, loc: Node, exp: Arg) extends Command
-case class Stop(sourceInfo: SourceInfo, clock: Arg, ret: Int) extends Command
-case class Port(id: Data, dir: SpecifiedDirection)
-case class Printf(sourceInfo: SourceInfo, clock: Arg, pable: Printable) extends Command
-abstract class Component extends Arg {
- def id: BaseModule
- def name: String
- def ports: Seq[Port]
-}
-case class DefModule(id: RawModule, name: String, ports: Seq[Port], commands: Seq[Command]) 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] = Seq.empty)