summaryrefslogtreecommitdiff
path: root/src/main/scala/Chisel/internal
diff options
context:
space:
mode:
authorducky2016-05-05 11:50:39 -0700
committerducky2016-05-05 11:50:39 -0700
commit9036d96bb032c19de31131f2296120e708cbc3dc (patch)
treecf17173fab309b09670ca7529680e09d61341451 /src/main/scala/Chisel/internal
parent623a301df1f5a1954f8e4a64ef97c99c3900da28 (diff)
Move Chisel API into separate chiselFrontend compilation unit in preparation for source locator macros
Diffstat (limited to 'src/main/scala/Chisel/internal')
-rw-r--r--src/main/scala/Chisel/internal/Builder.scala122
-rw-r--r--src/main/scala/Chisel/internal/Error.scala91
-rw-r--r--src/main/scala/Chisel/internal/firrtl/Emitter.scala101
-rw-r--r--src/main/scala/Chisel/internal/firrtl/IR.scala187
4 files changed, 0 insertions, 501 deletions
diff --git a/src/main/scala/Chisel/internal/Builder.scala b/src/main/scala/Chisel/internal/Builder.scala
deleted file mode 100644
index c7ecdaa0..00000000
--- a/src/main/scala/Chisel/internal/Builder.scala
+++ /dev/null
@@ -1,122 +0,0 @@
-// See LICENSE for license details.
-
-package Chisel.internal
-
-import scala.util.DynamicVariable
-import scala.collection.mutable.{ArrayBuffer, HashMap}
-
-import Chisel._
-import Chisel.internal.firrtl._
-
-private[Chisel] class Namespace(parent: Option[Namespace], keywords: Set[String]) {
- private var i = 0L
- private val names = collection.mutable.HashSet[String]()
-
- private def rename(n: String) = { i += 1; s"${n}_${i}" }
-
- def contains(elem: String): Boolean = {
- keywords.contains(elem) || names.contains(elem) ||
- parent.map(_ contains elem).getOrElse(false)
- }
-
- def name(elem: String): String = {
- if (this contains elem) {
- name(rename(elem))
- } else {
- names += elem
- elem
- }
- }
-
- def child(kws: Set[String]): Namespace = new Namespace(Some(this), kws)
- def child: Namespace = child(Set())
-}
-
-private[Chisel] class IdGen {
- private var counter = -1L
- def next: Long = {
- counter += 1
- counter
- }
-}
-
-private[Chisel] trait HasId {
- private[Chisel] def _onModuleClose {} // scalastyle:ignore method.name
- private[Chisel] val _parent = Builder.dynamicContext.currentModule
- _parent.foreach(_.addId(this))
-
- private[Chisel] val _id = Builder.idGen.next
- override def hashCode: Int = _id.toInt
- override def equals(that: Any): Boolean = that match {
- case x: HasId => _id == x._id
- case _ => false
- }
-
- // Facilities for 'suggesting' a name to this.
- // Post-name hooks called to carry the suggestion to other candidates as needed
- private var suggested_name: Option[String] = None
- private val postname_hooks = scala.collection.mutable.ListBuffer.empty[String=>Unit]
- // Only takes the first suggestion!
- def suggestName(name: =>String): this.type = {
- if(suggested_name.isEmpty) suggested_name = Some(name)
- for(hook <- postname_hooks) { hook(name) }
- this
- }
- private[Chisel] def addPostnameHook(hook: String=>Unit): Unit = postname_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 Bundle)
- private[Chisel] def forceName(default: =>String, namespace: Namespace): Unit =
- if(_ref.isEmpty) {
- val candidate_name = suggested_name.getOrElse(default)
- val available_name = namespace.name(candidate_name)
- setRef(Ref(available_name))
- }
-
- private var _ref: Option[Arg] = None
- private[Chisel] def setRef(imm: Arg): Unit = _ref = Some(imm)
- private[Chisel] def setRef(parent: HasId, name: String): Unit = setRef(Slot(Node(parent), name))
- private[Chisel] def setRef(parent: HasId, index: Int): Unit = setRef(Index(Node(parent), ILit(index)))
- private[Chisel] def setRef(parent: HasId, index: UInt): Unit = setRef(Index(Node(parent), index.ref))
- private[Chisel] def getRef: Arg = _ref.get
-}
-
-private[Chisel] class DynamicContext {
- val idGen = new IdGen
- val globalNamespace = new Namespace(None, Set())
- val components = ArrayBuffer[Component]()
- var currentModule: Option[Module] = None
- val errors = new ErrorLog
-}
-
-private[Chisel] object Builder {
- // All global mutable state must be referenced via dynamicContextVar!!
- private val dynamicContextVar = new DynamicVariable[Option[DynamicContext]](None)
-
- def dynamicContext: DynamicContext = dynamicContextVar.value.get
- def idGen: IdGen = dynamicContext.idGen
- def globalNamespace: Namespace = dynamicContext.globalNamespace
- def components: ArrayBuffer[Component] = dynamicContext.components
-
- def pushCommand[T <: Command](c: T): T = {
- dynamicContext.currentModule.foreach(_._commands += c)
- c
- }
- def pushOp[T <: Data](cmd: DefPrim[T]): T = pushCommand(cmd).id
-
- def errors: ErrorLog = dynamicContext.errors
- def error(m: => String): Unit = errors.error(m)
-
- def build[T <: Module](f: => T): Circuit = {
- dynamicContextVar.withValue(Some(new DynamicContext)) {
- errors.info("Elaborating design...")
- val mod = f
- mod.forceName(mod.name, globalNamespace)
- errors.checkpoint()
- errors.info("Done elaborating.")
-
- Circuit(components.last.name, components)
- }
- }
-}
diff --git a/src/main/scala/Chisel/internal/Error.scala b/src/main/scala/Chisel/internal/Error.scala
deleted file mode 100644
index 6c4c0880..00000000
--- a/src/main/scala/Chisel/internal/Error.scala
+++ /dev/null
@@ -1,91 +0,0 @@
-// See LICENSE for license details.
-
-package Chisel.internal
-
-import scala.collection.mutable.ArrayBuffer
-
-import Chisel._
-
-class ChiselException(message: String, cause: Throwable) extends Exception(message, cause)
-
-private[Chisel] object throwException {
- def apply(s: String, t: Throwable = null): Nothing =
- throw new ChiselException(s, t)
-}
-
-/** Records and reports runtime errors and warnings. */
-private[Chisel] class ErrorLog {
- def hasErrors: Boolean = errors.exists(_.isFatal)
-
- /** Log an error message */
- def error(m: => String): Unit =
- errors += new Error(m, getUserLineNumber)
-
- /** Log a warning message */
- def warning(m: => String): Unit =
- errors += new Warning(m, getUserLineNumber)
-
- /** Emit an informational message */
- def info(m: String): Unit =
- println(new Info("[%2.3f] %s".format(elapsedTime/1e3, m), None)) // scalastyle:ignore regex
-
- /** Prints error messages generated by Chisel at runtime. */
- def report(): Unit = errors foreach println // scalastyle:ignore regex
-
- /** Throw an exception if any errors have yet occurred. */
- def checkpoint(): Unit = if(hasErrors) {
- import Console._
- throwException(errors.map(_ + "\n").reduce(_ + _) +
- UNDERLINED + "CODE HAS " + errors.filter(_.isFatal).length + RESET +
- UNDERLINED + " " + RED + "ERRORS" + RESET +
- UNDERLINED + " and " + errors.filterNot(_.isFatal).length + RESET +
- UNDERLINED + " " + YELLOW + "WARNINGS" + RESET)
- }
-
- private def findFirstUserFrame(stack: Array[StackTraceElement]): Option[StackTraceElement] = {
- def isUserCode(ste: StackTraceElement): Boolean = {
- def isUserModule(c: Class[_]): Boolean =
- c != null && (c == classOf[Module] || isUserModule(c.getSuperclass))
- isUserModule(Class.forName(ste.getClassName))
- }
-
- stack.indexWhere(isUserCode) match {
- case x if x < 0 => None
- case x => Some(stack(x))
- }
- }
-
- private def getUserLineNumber =
- findFirstUserFrame(Thread.currentThread().getStackTrace)
-
- private val errors = ArrayBuffer[LogEntry]()
-
- private val startTime = System.currentTimeMillis
- private def elapsedTime: Long = System.currentTimeMillis - startTime
-}
-
-private abstract class LogEntry(msg: => String, line: Option[StackTraceElement]) {
- def isFatal: Boolean = false
- def format: String
-
- 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}"
- }
-
- protected def tag(name: String, color: String): String =
- s"[${color}${name}${Console.RESET}]"
-}
-
-private class Error(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) {
- override def isFatal: Boolean = true
- def format: String = tag("error", Console.RED)
-}
-
-private class Warning(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) {
- def format: String = tag("warn", Console.YELLOW)
-}
-
-private class Info(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) {
- def format: String = tag("info", Console.MAGENTA)
-}
diff --git a/src/main/scala/Chisel/internal/firrtl/Emitter.scala b/src/main/scala/Chisel/internal/firrtl/Emitter.scala
deleted file mode 100644
index b690d974..00000000
--- a/src/main/scala/Chisel/internal/firrtl/Emitter.scala
+++ /dev/null
@@ -1,101 +0,0 @@
-// See LICENSE for license details.
-
-package Chisel.internal.firrtl
-import Chisel._
-
-private class Emitter(circuit: Circuit) {
- override def toString: String = res.toString
-
- private def emitPort(e: Port): String =
- s"${e.dir} ${e.id.getRef.name} : ${e.id.toType}"
- private def emit(e: Command, ctx: Component): String = e match {
- case e: DefPrim[_] => s"node ${e.name} = ${e.op.name}(${e.args.map(_.fullName(ctx)).mkString(", ")})"
- case e: DefWire => s"wire ${e.name} : ${e.id.toType}"
- case e: DefReg => s"reg ${e.name} : ${e.id.toType}, ${e.clock.fullName(ctx)}"
- case e: DefRegInit => s"reg ${e.name} : ${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.t.toType}[${e.size}]"
- case e: DefSeqMemory => s"smem ${e.name} : ${e.t.toType}[${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)}"
- case e: Stop => s"stop(${e.clk.fullName(ctx)}, UInt<1>(1), ${e.ret})"
- case e: Printf => s"""printf(${e.clk.fullName(ctx)}, UInt<1>(1), "${e.format}"${e.ids.map(_.fullName(ctx)).fold(""){_ + ", " + _}})"""
- case e: DefInvalid => s"${e.arg.fullName(ctx)} is invalid"
- case e: DefInstance => {
- val modName = moduleMap.get(e.id.name).get
- s"inst ${e.name} of $modName"
- }
-
- case w: WhenBegin =>
- indent()
- s"when ${w.pred.fullName(ctx)} :"
- case _: WhenEnd =>
- unindent()
- "skip"
- }
-
- // Map of Module FIRRTL definition to FIRRTL name, if it has been emitted already.
- private val defnMap = collection.mutable.HashMap[String, String]()
- // Map of Component name to FIRRTL id.
- private val moduleMap = collection.mutable.HashMap[String, String]()
-
- /** Generates the FIRRTL module definition with a specified name.
- */
- private def moduleDefn(m: Component, name: String): String = {
- val body = new StringBuilder
- m.id match {
- case _: BlackBox => body ++= newline + s"extmodule $name : "
- case _: Module => body ++= newline + s"module $name : "
- }
- withIndent {
- for (p <- m.ports)
- body ++= newline + emitPort(p)
- body ++= newline
-
- m.id match {
- case _: BlackBox =>
- // TODO: BlackBoxes should be empty, but funkiness in Module() means
- // it's not for now. Eventually, this should assert out.
- case _: Module => for (cmd <- m.commands) {
- body ++= newline + emit(cmd, 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).
- */
- private def emit(m: Component): String = {
- // Generate the body.
- val moduleName = m.id.getClass.getName.split('.').last
- val defn = moduleDefn(m, moduleName)
-
- defnMap get defn match {
- case Some(deduplicatedName) =>
- moduleMap(m.name) = deduplicatedName
- ""
- case None =>
- require(!(moduleMap contains m.name),
- "emitting module with same name but different contents")
-
- moduleMap(m.name) = m.name
- defnMap(defn) = m.name
-
- moduleDefn(m, m.name)
- }
- }
-
- private var indentLevel = 0
- private def newline = "\n" + (" " * indentLevel)
- private def indent(): Unit = indentLevel += 1
- private def unindent() { require(indentLevel > 0); indentLevel -= 1 }
- private def withIndent(f: => Unit) { indent(); f; unindent() }
-
- private val res = new StringBuilder(s"circuit ${circuit.name} : ")
- withIndent { circuit.components.foreach(c => res ++= emit(c)) }
- res ++= newline
-}
diff --git a/src/main/scala/Chisel/internal/firrtl/IR.scala b/src/main/scala/Chisel/internal/firrtl/IR.scala
deleted file mode 100644
index 1e06a663..00000000
--- a/src/main/scala/Chisel/internal/firrtl/IR.scala
+++ /dev/null
@@ -1,187 +0,0 @@
-// See LICENSE for license details.
-
-package Chisel.internal.firrtl
-import Chisel._
-import Chisel.internal._
-
-case class PrimOp(val 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 XorReduceOp = PrimOp("xorr")
- val ConvertOp = PrimOp("cvt")
- val AsUIntOp = PrimOp("asUInt")
- val AsSIntOp = PrimOp("asSInt")
-}
-
-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.getRef.fullName(ctx)
- def name: String = id.getRef.name
-}
-
-abstract class LitArg(val num: BigInt, widthArg: Width) extends Arg {
- private[Chisel] def forcedWidth = widthArg.known
- private[Chisel] def width: Width = if (forcedWidth) widthArg else Width(minWidth)
-
- protected def minWidth: Int
- if (forcedWidth) {
- require(widthArg.get >= minWidth,
- s"The literal value ${num} was elaborated with a specificed width of ${widthArg.get} bits, but at least ${minWidth} bits are required.")
- }
-}
-
-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 Ref(name: String) extends Arg
-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"
-}
-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}>"
-}
-
-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")
-}
-
-abstract class Command
-abstract class Definition extends Command {
- def id: HasId
- def name: String = id.getRef.name
-}
-case class DefPrim[T <: Data](id: T, op: PrimOp, args: Arg*) extends Definition
-case class DefInvalid(arg: Arg) extends Command
-case class DefWire(id: Data) extends Definition
-case class DefReg(id: Data, clock: Arg) extends Definition
-case class DefRegInit(id: Data, clock: Arg, reset: Arg, init: Arg) extends Definition
-case class DefMemory(id: HasId, t: Data, size: Int) extends Definition
-case class DefSeqMemory(id: HasId, t: Data, size: Int) extends Definition
-case class DefMemPort[T <: Data](id: T, source: Node, dir: MemPortDirection, index: Arg, clock: Arg) extends Definition
-case class DefInstance(id: Module, ports: Seq[Port]) extends Definition
-case class WhenBegin(pred: Arg) extends Command
-case class WhenEnd() extends Command
-case class Connect(loc: Node, exp: Arg) extends Command
-case class BulkConnect(loc1: Node, loc2: Node) extends Command
-case class ConnectInit(loc: Node, exp: Arg) extends Command
-case class Stop(clk: Arg, ret: Int) extends Command
-case class Component(id: Module, name: String, ports: Seq[Port], commands: Seq[Command]) extends Arg
-case class Port(id: Data, dir: Direction)
-case class Printf(clk: Arg, formatIn: String, ids: Seq[Arg]) extends Command {
- require(formatIn.forall(c => c.toInt > 0 && c.toInt < 128), "format strings must comprise non-null ASCII values")
- def format: String = {
- def escaped(x: Char) = {
- require(x.toInt >= 0)
- if (x == '"' || x == '\\') {
- s"\\${x}"
- } else if (x == '\n') {
- "\\n"
- } else {
- require(x.toInt >= 32) // TODO \xNN once FIRRTL issue #59 is resolved
- x
- }
- }
- formatIn.map(escaped _).mkString
- }
-}
-
-case class Circuit(name: String, components: Seq[Component]) {
- def emit: String = new Emitter(this).toString
-}