From d6c7044bff31aae09931df8d4350d29414b37447 Mon Sep 17 00:00:00 2001 From: ducky Date: Mon, 26 Oct 2015 17:42:03 -0700 Subject: Move internal files into their own directories --- src/main/scala/Chisel/Builder.scala | 118 -------------------- src/main/scala/Chisel/Emitter.scala | 73 ------------- src/main/scala/Chisel/Error.scala | 88 --------------- src/main/scala/Chisel/IR.scala | 157 --------------------------- src/main/scala/Chisel/internal/Builder.scala | 118 ++++++++++++++++++++ src/main/scala/Chisel/internal/Error.scala | 88 +++++++++++++++ src/main/scala/Chisel/ir/Emitter.scala | 73 +++++++++++++ src/main/scala/Chisel/ir/IR.scala | 157 +++++++++++++++++++++++++++ 8 files changed, 436 insertions(+), 436 deletions(-) delete mode 100644 src/main/scala/Chisel/Builder.scala delete mode 100644 src/main/scala/Chisel/Emitter.scala delete mode 100644 src/main/scala/Chisel/Error.scala delete mode 100644 src/main/scala/Chisel/IR.scala create mode 100644 src/main/scala/Chisel/internal/Builder.scala create mode 100644 src/main/scala/Chisel/internal/Error.scala create mode 100644 src/main/scala/Chisel/ir/Emitter.scala create mode 100644 src/main/scala/Chisel/ir/IR.scala (limited to 'src') diff --git a/src/main/scala/Chisel/Builder.scala b/src/main/scala/Chisel/Builder.scala deleted file mode 100644 index b3c4ae40..00000000 --- a/src/main/scala/Chisel/Builder.scala +++ /dev/null @@ -1,118 +0,0 @@ -// See LICENSE for license details. - -package Chisel -import scala.util.DynamicVariable -import scala.collection.mutable.{ArrayBuffer, HashMap} - -private 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 class IdGen { - private var counter = -1L - def next: Long = { - counter += 1 - counter - } -} - -private[Chisel] trait HasId { - private[Chisel] def _onModuleClose {} - private[Chisel] val _parent = Builder.dynamicContext.currentModule - _parent.foreach(_.addId(this)) - - private[Chisel] val _refMap = Builder.globalRefMap - private[Chisel] val _id = Builder.idGen.next - private[Chisel] def setRef(imm: Arg) = _refMap.setRef(this, imm) - private[Chisel] def setRef(name: String) = _refMap.setRef(this, name) - private[Chisel] def setRef(parent: HasId, name: String) = _refMap.setField(parent, this, name) - private[Chisel] def setRef(parent: HasId, index: Int) = _refMap.setIndex(parent, this, index) - private[Chisel] def getRef = _refMap(this) -} - -class RefMap { - private val _refmap = new HashMap[Long,Arg]() - - private[Chisel] def setRef(id: HasId, ref: Arg): Unit = - _refmap(id._id) = ref - - private[Chisel] def setRef(id: HasId, name: String): Unit = - if (!_refmap.contains(id._id)) setRef(id, Ref(name)) - - private[Chisel] def setField(parentid: HasId, id: HasId, name: String): Unit = - _refmap(id._id) = Slot(Node(parentid), name) - - private[Chisel] def setIndex(parentid: HasId, id: HasId, index: Int): Unit = - _refmap(id._id) = Index(Node(parentid), index) - - def apply(id: HasId): Arg = _refmap(id._id) -} - -private class DynamicContext { - val idGen = new IdGen - val globalNamespace = new Namespace(None, Set()) - val globalRefMap = new RefMap - val components = ArrayBuffer[Component]() - var currentModule: Option[Module] = None - val parameterDump = new ParameterDump - val errors = new ErrorLog -} - -private object Builder { - // All global mutable state must be referenced via dynamicContextVar!! - private val dynamicContextVar = new DynamicVariable[Option[DynamicContext]](None) - private val currentParamsVar = new DynamicVariable[Parameters](Parameters.empty) - - def dynamicContext: DynamicContext = dynamicContextVar.value.get - def idGen: IdGen = dynamicContext.idGen - def globalNamespace: Namespace = dynamicContext.globalNamespace - def globalRefMap: RefMap = dynamicContext.globalRefMap - def components: ArrayBuffer[Component] = dynamicContext.components - def parameterDump: ParameterDump = dynamicContext.parameterDump - - 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 getParams: Parameters = currentParamsVar.value - def paramsScope[T](p: Parameters)(body: => T): T = { - currentParamsVar.withValue(p)(body) - } - - def build[T <: Module](f: => T): Circuit = { - dynamicContextVar.withValue(Some(new DynamicContext)) { - errors.info("Elaborating design...") - val mod = f - mod.setRef(globalNamespace.name(mod.name)) - errors.checkpoint() - errors.info("Done elaborating.") - - Circuit(components.last.name, components, globalRefMap, parameterDump) - } - } -} diff --git a/src/main/scala/Chisel/Emitter.scala b/src/main/scala/Chisel/Emitter.scala deleted file mode 100644 index b4689d61..00000000 --- a/src/main/scala/Chisel/Emitter.scala +++ /dev/null @@ -1,73 +0,0 @@ -// See LICENSE for license details. - -package 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)).reduce(_ + ", " + _)})" - case e: DefWire => s"wire ${e.name} : ${e.id.toType}" - case e: DefPoison[_] => s"poison ${e.name} : ${e.id.toType}" - case e: DefRegister => s"reg ${e.name} : ${e.id.toType}, ${e.clock.fullName(ctx)}, ${e.reset.fullName(ctx)}" - case e: DefMemory => s"cmem ${e.name} : ${e.t.toType}[${e.size}], ${e.clock.fullName(ctx)}" - case e: DefSeqMemory => s"smem ${e.name} : ${e.t.toType}[${e.size}], ${e.clock.fullName(ctx)}" - case e: DefAccessor[_] => s"infer accessor ${e.name} = ${e.source.fullName(ctx)}[${e.index.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: ConnectInit => s"onreset ${e.loc.fullName(ctx)} := ${e.exp.fullName(ctx)}" - case e: DefInstance => { - val modName = moduleMap.getOrElse(e.id.name, e.id.name) - s"inst ${e.name} of $modName" - } - - case w: WhenBegin => - indent() - s"when ${w.pred.fullName(ctx)} :" - case _: WhenElse => - indent() - "else :" - case _: WhenEnd => - unindent() - "skip" - } - private def emitBody(m: Component) = { - val me = new StringBuilder - withIndent { - for (p <- m.ports) - me ++= newline + emitPort(p) - me ++= newline - for (cmd <- m.commands) - me ++= newline + emit(cmd, m) - me ++= newline - } - me - } - - private val bodyMap = collection.mutable.HashMap[StringBuilder, String]() - private val moduleMap = collection.mutable.HashMap[String, String]() - - private def emit(m: Component): String = { - val body = emitBody(m) - bodyMap get body match { - case Some(name) => - moduleMap(m.name) = name - "" - case None => - bodyMap(body) = m.name - newline + s"module ${m.name} : " + body - } - } - - 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/Error.scala b/src/main/scala/Chisel/Error.scala deleted file mode 100644 index 30f6b527..00000000 --- a/src/main/scala/Chisel/Error.scala +++ /dev/null @@ -1,88 +0,0 @@ -// See LICENSE for license details. - -package Chisel -import scala.collection.mutable.ArrayBuffer - -class ChiselException(message: String, cause: Throwable) extends Exception(message, cause) - -private object throwException { - def apply(s: String, t: Throwable = null): Nothing = - throw new ChiselException(s, t) -} - -/** Records and reports runtime errors and warnings. */ -private 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)) - - /** Prints error messages generated by Chisel at runtime. */ - def report(): Unit = errors foreach println - - /** 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/IR.scala b/src/main/scala/Chisel/IR.scala deleted file mode 100644 index e25d3f56..00000000 --- a/src/main/scala/Chisel/IR.scala +++ /dev/null @@ -1,157 +0,0 @@ -// See LICENSE for license details. - -package Chisel - -case class PrimOp(val name: String) { - override def toString: String = name -} - -object PrimOp { - val AddOp = PrimOp("add") - val AddModOp = PrimOp("addw") - val SubOp = PrimOp("sub") - val SubModOp = PrimOp("subw") - val TimesOp = PrimOp("mul") - val DivideOp = PrimOp("div") - val ModOp = PrimOp("mod") - 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 BitSelectOp = PrimOp("bit") - 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) - } -} - -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: Int) extends Arg { - def name: String = s"[$value]" - override def fullName(ctx: Component): String = s"${imm.fullName(ctx)}[$value]" -} - -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 = value.toString -} - -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 DefWire(id: Data) extends Definition -case class DefRegister(id: Data, clock: Arg, reset: Arg) extends Definition -case class DefMemory(id: HasId, t: Data, size: Int, clock: Arg) extends Definition -case class DefSeqMemory(id: HasId, t: Data, size: Int, clock: Arg) extends Definition -case class DefAccessor[T <: Data](id: T, source: Node, direction: Direction, index: Arg) extends Definition -case class DefInstance(id: Module, ports: Seq[Port]) extends Definition -case class DefPoison[T <: Data](id: T) extends Definition -case class WhenBegin(pred: Arg) extends Command -case class WhenElse() 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 Component(id: Module, name: String, ports: Seq[Port], commands: Seq[Command]) extends Arg -case class Port(id: Data, dir: Direction) - -case class Circuit(name: String, components: Seq[Component], refMap: RefMap, parameterDump: ParameterDump) { - def emit: String = new Emitter(this).toString -} diff --git a/src/main/scala/Chisel/internal/Builder.scala b/src/main/scala/Chisel/internal/Builder.scala new file mode 100644 index 00000000..b3c4ae40 --- /dev/null +++ b/src/main/scala/Chisel/internal/Builder.scala @@ -0,0 +1,118 @@ +// See LICENSE for license details. + +package Chisel +import scala.util.DynamicVariable +import scala.collection.mutable.{ArrayBuffer, HashMap} + +private 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 class IdGen { + private var counter = -1L + def next: Long = { + counter += 1 + counter + } +} + +private[Chisel] trait HasId { + private[Chisel] def _onModuleClose {} + private[Chisel] val _parent = Builder.dynamicContext.currentModule + _parent.foreach(_.addId(this)) + + private[Chisel] val _refMap = Builder.globalRefMap + private[Chisel] val _id = Builder.idGen.next + private[Chisel] def setRef(imm: Arg) = _refMap.setRef(this, imm) + private[Chisel] def setRef(name: String) = _refMap.setRef(this, name) + private[Chisel] def setRef(parent: HasId, name: String) = _refMap.setField(parent, this, name) + private[Chisel] def setRef(parent: HasId, index: Int) = _refMap.setIndex(parent, this, index) + private[Chisel] def getRef = _refMap(this) +} + +class RefMap { + private val _refmap = new HashMap[Long,Arg]() + + private[Chisel] def setRef(id: HasId, ref: Arg): Unit = + _refmap(id._id) = ref + + private[Chisel] def setRef(id: HasId, name: String): Unit = + if (!_refmap.contains(id._id)) setRef(id, Ref(name)) + + private[Chisel] def setField(parentid: HasId, id: HasId, name: String): Unit = + _refmap(id._id) = Slot(Node(parentid), name) + + private[Chisel] def setIndex(parentid: HasId, id: HasId, index: Int): Unit = + _refmap(id._id) = Index(Node(parentid), index) + + def apply(id: HasId): Arg = _refmap(id._id) +} + +private class DynamicContext { + val idGen = new IdGen + val globalNamespace = new Namespace(None, Set()) + val globalRefMap = new RefMap + val components = ArrayBuffer[Component]() + var currentModule: Option[Module] = None + val parameterDump = new ParameterDump + val errors = new ErrorLog +} + +private object Builder { + // All global mutable state must be referenced via dynamicContextVar!! + private val dynamicContextVar = new DynamicVariable[Option[DynamicContext]](None) + private val currentParamsVar = new DynamicVariable[Parameters](Parameters.empty) + + def dynamicContext: DynamicContext = dynamicContextVar.value.get + def idGen: IdGen = dynamicContext.idGen + def globalNamespace: Namespace = dynamicContext.globalNamespace + def globalRefMap: RefMap = dynamicContext.globalRefMap + def components: ArrayBuffer[Component] = dynamicContext.components + def parameterDump: ParameterDump = dynamicContext.parameterDump + + 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 getParams: Parameters = currentParamsVar.value + def paramsScope[T](p: Parameters)(body: => T): T = { + currentParamsVar.withValue(p)(body) + } + + def build[T <: Module](f: => T): Circuit = { + dynamicContextVar.withValue(Some(new DynamicContext)) { + errors.info("Elaborating design...") + val mod = f + mod.setRef(globalNamespace.name(mod.name)) + errors.checkpoint() + errors.info("Done elaborating.") + + Circuit(components.last.name, components, globalRefMap, parameterDump) + } + } +} diff --git a/src/main/scala/Chisel/internal/Error.scala b/src/main/scala/Chisel/internal/Error.scala new file mode 100644 index 00000000..30f6b527 --- /dev/null +++ b/src/main/scala/Chisel/internal/Error.scala @@ -0,0 +1,88 @@ +// See LICENSE for license details. + +package Chisel +import scala.collection.mutable.ArrayBuffer + +class ChiselException(message: String, cause: Throwable) extends Exception(message, cause) + +private object throwException { + def apply(s: String, t: Throwable = null): Nothing = + throw new ChiselException(s, t) +} + +/** Records and reports runtime errors and warnings. */ +private 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)) + + /** Prints error messages generated by Chisel at runtime. */ + def report(): Unit = errors foreach println + + /** 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/ir/Emitter.scala b/src/main/scala/Chisel/ir/Emitter.scala new file mode 100644 index 00000000..b4689d61 --- /dev/null +++ b/src/main/scala/Chisel/ir/Emitter.scala @@ -0,0 +1,73 @@ +// See LICENSE for license details. + +package 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)).reduce(_ + ", " + _)})" + case e: DefWire => s"wire ${e.name} : ${e.id.toType}" + case e: DefPoison[_] => s"poison ${e.name} : ${e.id.toType}" + case e: DefRegister => s"reg ${e.name} : ${e.id.toType}, ${e.clock.fullName(ctx)}, ${e.reset.fullName(ctx)}" + case e: DefMemory => s"cmem ${e.name} : ${e.t.toType}[${e.size}], ${e.clock.fullName(ctx)}" + case e: DefSeqMemory => s"smem ${e.name} : ${e.t.toType}[${e.size}], ${e.clock.fullName(ctx)}" + case e: DefAccessor[_] => s"infer accessor ${e.name} = ${e.source.fullName(ctx)}[${e.index.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: ConnectInit => s"onreset ${e.loc.fullName(ctx)} := ${e.exp.fullName(ctx)}" + case e: DefInstance => { + val modName = moduleMap.getOrElse(e.id.name, e.id.name) + s"inst ${e.name} of $modName" + } + + case w: WhenBegin => + indent() + s"when ${w.pred.fullName(ctx)} :" + case _: WhenElse => + indent() + "else :" + case _: WhenEnd => + unindent() + "skip" + } + private def emitBody(m: Component) = { + val me = new StringBuilder + withIndent { + for (p <- m.ports) + me ++= newline + emitPort(p) + me ++= newline + for (cmd <- m.commands) + me ++= newline + emit(cmd, m) + me ++= newline + } + me + } + + private val bodyMap = collection.mutable.HashMap[StringBuilder, String]() + private val moduleMap = collection.mutable.HashMap[String, String]() + + private def emit(m: Component): String = { + val body = emitBody(m) + bodyMap get body match { + case Some(name) => + moduleMap(m.name) = name + "" + case None => + bodyMap(body) = m.name + newline + s"module ${m.name} : " + body + } + } + + 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/ir/IR.scala b/src/main/scala/Chisel/ir/IR.scala new file mode 100644 index 00000000..e25d3f56 --- /dev/null +++ b/src/main/scala/Chisel/ir/IR.scala @@ -0,0 +1,157 @@ +// See LICENSE for license details. + +package Chisel + +case class PrimOp(val name: String) { + override def toString: String = name +} + +object PrimOp { + val AddOp = PrimOp("add") + val AddModOp = PrimOp("addw") + val SubOp = PrimOp("sub") + val SubModOp = PrimOp("subw") + val TimesOp = PrimOp("mul") + val DivideOp = PrimOp("div") + val ModOp = PrimOp("mod") + 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 BitSelectOp = PrimOp("bit") + 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) + } +} + +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: Int) extends Arg { + def name: String = s"[$value]" + override def fullName(ctx: Component): String = s"${imm.fullName(ctx)}[$value]" +} + +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 = value.toString +} + +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 DefWire(id: Data) extends Definition +case class DefRegister(id: Data, clock: Arg, reset: Arg) extends Definition +case class DefMemory(id: HasId, t: Data, size: Int, clock: Arg) extends Definition +case class DefSeqMemory(id: HasId, t: Data, size: Int, clock: Arg) extends Definition +case class DefAccessor[T <: Data](id: T, source: Node, direction: Direction, index: Arg) extends Definition +case class DefInstance(id: Module, ports: Seq[Port]) extends Definition +case class DefPoison[T <: Data](id: T) extends Definition +case class WhenBegin(pred: Arg) extends Command +case class WhenElse() 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 Component(id: Module, name: String, ports: Seq[Port], commands: Seq[Command]) extends Arg +case class Port(id: Data, dir: Direction) + +case class Circuit(name: String, components: Seq[Component], refMap: RefMap, parameterDump: ParameterDump) { + def emit: String = new Emitter(this).toString +} -- cgit v1.2.3