summaryrefslogtreecommitdiff
path: root/src/main/scala/Chisel/Core.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/Chisel/Core.scala')
-rw-r--r--src/main/scala/Chisel/Core.scala280
1 files changed, 115 insertions, 165 deletions
diff --git a/src/main/scala/Chisel/Core.scala b/src/main/scala/Chisel/Core.scala
index 2514c7d9..7fdd35bf 100644
--- a/src/main/scala/Chisel/Core.scala
+++ b/src/main/scala/Chisel/Core.scala
@@ -6,7 +6,7 @@ import java.lang.reflect.Modifier._
import java.lang.Double.longBitsToDouble
import java.lang.Float.intBitsToFloat
-class IdGen {
+private class IdGen {
private var counter = -1L
def next: Long = {
counter += 1
@@ -38,73 +38,34 @@ private class ChiselRefMap {
}
private object DynamicContext {
- val currentParentVar = new DynamicVariable[Option[Module]](None)
+ val currentModuleVar = new DynamicVariable[Option[Module]](None)
val currentParamsVar = new DynamicVariable[Parameters](Parameters.empty)
- val currentCommandsVar = new DynamicVariable[ArrayBuffer[Command]](new ArrayBuffer[Command]())
- def getParentModule = currentParentVar.value
- def parentModuleScope[T](m: Option[Module])(body: => T): T = {
- currentParentVar.withValue(m)(body)
+ def getCurrentModule = currentModuleVar.value
+ def moduleScope[T](body: => T): T = {
+ currentModuleVar.withValue(getCurrentModule)(body)
}
- def forceParentModule[T](m: Module) {
- currentParentVar.value = Some(m)
+ def forceCurrentModule[T](m: Module) { // Used in Module constructor
+ currentModuleVar.value = Some(m)
+ }
+ def pushCommand(c: Command) {
+ currentModuleVar.value.foreach(_._commands += c)
}
def getParams: Parameters = currentParamsVar.value
def paramsScope[T](p: Parameters)(body: => T): T = {
currentParamsVar.withValue(p)(body)
}
-
- def getCommands: Command = {
- val cmds = currentCommandsVar.value
- if (cmds.length == 0) EmptyCommand()
- else if (cmds.length == 1) cmds(0)
- else Begin(cmds.toList)
- }
- def pushCommand(c: Command) {
- currentCommandsVar.value += c
- }
- def commandsScope[T](body: => T): (T, Command) = {
- currentCommandsVar.withValue(new ArrayBuffer[Command]()){
- val r = body
- val c = getCommands
- (r, c)
- }
- }
}
private object Builder {
- val globalNamespace = new FIRRTLNamespace
- val globalRefMap = new ChiselRefMap
val idGen = new IdGen
-
- val components = new ArrayBuffer[Component]()
- val commandz = new Stack[ArrayBuffer[Command]]()
- def commands = commandz.top
- def pushCommand(cmd: Command) = commands += cmd
- def commandify(cmds: ArrayBuffer[Command]): Command = {
- if (cmds.length == 0)
- EmptyCommand()
- else if (cmds.length == 1)
- cmds(0)
- else
- Begin(cmds.toList)
- }
- def pushCommands =
- commandz.push(new ArrayBuffer[Command]())
- def popCommands: Command = {
- val newCommands = commands
- commandz.pop()
- commandify(newCommands)
- }
- def collectCommands[T <: Module](f: => T): (Command, T) = {
- pushCommands
- val mod = f
- (popCommands, mod)
- }
+ val globalNamespace = new FIRRTLNamespace
+ val globalRefMap = new ChiselRefMap // TODO: mutable
+ val components = new ArrayBuffer[Component]() //TODO: mutable
def build[T <: Module](f: => T): Circuit = {
- val (cmd, mod) = collectCommands(f)
+ val mod = f
Builder.globalRefMap.setRefForId(mod, mod.name)
Circuit(components, components.last.name)
}
@@ -116,9 +77,7 @@ object build {
}
}
-import Builder.pushCommand
-import Builder.pushCommands
-import Builder.popCommands
+import DynamicContext.pushCommand
/// CHISEL IR
@@ -284,17 +243,16 @@ case class DefRegister(id: Id, kind: Kind, clock: Clock, reset: Bool) extends De
case class DefMemory(id: Id, kind: Kind, size: Int, clock: Clock) extends Definition
case class DefSeqMemory(id: Id, kind: Kind, size: Int) extends Definition
case class DefAccessor(id: Id, source: Alias, direction: Direction, index: Arg) extends Definition
-case class DefInstance(id: Module, module: String, ports: Seq[Port]) extends Definition
-case class Conditionally(val prep: Command, val pred: Arg, val conseq: Command, var alt: Command) extends Command;
-case class Begin(val body: List[Command]) extends Command();
-case class Connect(val loc: Alias, val exp: Arg) extends Command;
-case class BulkConnect(val loc1: Alias, val loc2: Alias) extends Command;
-case class ConnectInit(val loc: Alias, val exp: Arg) extends Command;
-case class ConnectInitIndex(val loc: Alias, val index: Int, val exp: Arg) extends Command;
-case class EmptyCommand() extends Command;
-
-case class Component(val name: String, val ports: Seq[Port], val body: Command);
-case class Circuit(val components: Seq[Component], val main: String);
+case class DefInstance(id: Module, ports: Seq[Port]) extends Definition
+case class WhenBegin(pred: Arg) extends Command
+case class WhenElse() extends Command
+case class WhenEnd() extends Command
+case class Connect(loc: Alias, exp: Arg) extends Command
+case class BulkConnect(loc1: Alias, loc2: Alias) extends Command
+case class ConnectInit(loc: Alias, exp: Arg) extends Command
+
+case class Component(name: String, ports: Seq[Port], commands: Seq[Command])
+case class Circuit(components: Seq[Component], main: String)
object Commands {
val NoLits = Seq[BigInt]()
@@ -324,11 +282,11 @@ object debug {
}
abstract class Data(dirArg: Direction) extends Id {
- private[Chisel] val _mod: Module = DynamicContext.getParentModule.getOrElse(
+ private[Chisel] val _mod: Module = DynamicContext.getCurrentModule.getOrElse(
throwException("Data subclasses can only be instantiated inside Modules!"))
//TODO: is this true?
- _mod.addNode(Some(this))
+ _mod.addNode(this)
def params = DynamicContext.getParams
def toType: Kind
@@ -336,16 +294,15 @@ abstract class Data(dirArg: Direction) extends Id {
// Sucks this is mutable state, but cloneType doesn't take a Direction arg
private var isFlipVar = dirArg == INPUT
- private[Chisel] var dirVar = dirArg
+ private var dirVar = dirArg
private[Chisel] def isFlip = isFlipVar
private def cloneWithDirection(newDir: Direction => Direction,
newFlip: Boolean => Boolean): this.type = {
val res = this.cloneType
res.isFlipVar = newFlip(res.isFlipVar)
- for ((me, it) <- this.flatten zip res.flatten) {
- it.dirVar = newDir(me.dirVar)
- }
+ for ((me, it) <- this.flatten zip res.flatten)
+ (it: Data).dirVar = newDir((me: Data).dirVar)
res
}
def asInput: this.type = cloneWithDirection(_ => INPUT, _ => true)
@@ -1033,8 +990,8 @@ class Bundle extends Aggregate(NO_DIR) {
case npe: java.lang.reflect.InvocationTargetException if npe.getCause.isInstanceOf[java.lang.NullPointerException] =>
ChiselError.error(s"Parameterized Bundle ${this.getClass} needs cloneType method. You are probably using an anonymous Bundle object that captures external state and hence is un-cloneTypeable")
this
- case e: java.lang.Exception =>
- ChiselError.error(s"Parameterized Bundle ${this.getClass} needs cloneType method")
+ case npe: java.lang.reflect.InvocationTargetException =>
+ ChiselError.error(s"Parameterized Bundle ${this.getClass} needs cloneType method")
this
}
}
@@ -1043,10 +1000,10 @@ class Bundle extends Aggregate(NO_DIR) {
object Module {
def apply[T <: Module](bc: => T)(implicit currParams: Parameters = DynamicContext.getParams): T = {
DynamicContext.paramsScope(currParams.push) {
- val m = DynamicContext.parentModuleScope(None) { bc.setRefs() }
+ val m = DynamicContext.moduleScope{ bc.setRefs() }
val ports = m.computePorts
- Builder.components += Component(m.name, ports, popCommands)
- pushCommand(DefInstance(m, m.name, ports))
+ Builder.components += Component(m.name, ports, m._commands)
+ pushCommand(DefInstance(m, ports))
m
}.connectImplicitIOs()
}
@@ -1057,13 +1014,13 @@ object Module {
}
abstract class Module(_clock: Clock = null, _reset: Bool = null) extends Id {
- private val _parent = DynamicContext.getParentModule
- private val _nodes = ArrayBuffer[Data]()
private implicit val _namespace = new ChildNamespace(Builder.globalNamespace)
- val name = Builder.globalNamespace.name(getClass.getName.split('.').last)
+ private[Chisel] val _commands = ArrayBuffer[Command]()
+ private[Chisel] val _nodes = ArrayBuffer[Data]()
+ private[Chisel] val _parent = DynamicContext.getCurrentModule
+ DynamicContext.forceCurrentModule(this)
- DynamicContext.forceParentModule(this)
- pushCommands
+ val name = Builder.globalNamespace.name(getClass.getName.split('.').last)
private def params = DynamicContext.getParams
params.path = this.getClass :: params.path //TODO: make immutable?
@@ -1075,7 +1032,7 @@ abstract class Module(_clock: Clock = null, _reset: Bool = null) extends Id {
private[Chisel] def ref = Builder.globalRefMap.getRefForId(this)
private[Chisel] def lref = ref
- def addNode(d: Option[Data]) { d.map(_nodes += _) }
+ def addNode(d: Data) { _nodes += d }
def debugName: String = _parent match {
case Some(p) => s"${p.debugName}.${ref.debugName}"
@@ -1140,57 +1097,38 @@ abstract class BlackBox(_clock: Clock = null, _reset: Bool = null) extends Modul
}
object when {
- private[Chisel] def execBlock(block: => Unit): Command = {
- pushCommands
- block
- val cmd = popCommands
- cmd
- }
- def apply(cond: => Bool)(block: => Unit): when = {
- new when(cond)( block )
+ def apply(cond: => Bool)(block: => Unit): WhenContext = {
+ new WhenContext(cond)(block)
}
}
-class when(cond: => Bool)(block: => Unit) {
- def elsewhen (cond: => Bool)(block: => Unit): when = {
- pushCommands
- val res = new when(cond) ( block )
- this.cmd.alt = popCommands
- res
- }
+class WhenContext(cond: => Bool)(block: => Unit) {
+ def elsewhen (cond: => Bool)(block: => Unit): WhenContext =
+ doOtherwise(when(cond)(block))
- def otherwise (block: => Unit) {
- this.cmd.alt = when.execBlock(block)
- }
+ def otherwise(block: => Unit): Unit =
+ doOtherwise(block)
+
+ pushCommand(WhenBegin(cond.ref))
+ block
+ pushCommand(WhenEnd())
- // Capture any commands we need to set up the conditional test.
- pushCommands
- val pred = cond.ref
- val prep = popCommands
- val conseq = when.execBlock(block)
- // Assume we have an empty alternate clause.
- // elsewhen and otherwise will update it if that isn't the case.
- val cmd = Conditionally(prep, pred, conseq, EmptyCommand())
- pushCommand(cmd)
+ private def doOtherwise[T](block: => T): T = {
+ pushCommand(WhenElse())
+ val res = block
+ pushCommand(WhenEnd())
+ res
+ }
}
/// CHISEL IR EMITTER
-class Emitter {
- private var indenting = 0
- def withIndent(f: => String) = {
- indenting += 1
- val res = f
- indenting -= 1
- res
- }
+class Emitter(circuit: Circuit) {
+ override def toString = res.toString
- def newline = "\n" + (" " * indenting)
def join(parts: Seq[String], sep: String): StringBuilder =
parts.tail.foldLeft(new StringBuilder(parts.head))((s, p) => s ++= sep ++= p)
- def join0(parts: Seq[String], sep: String): StringBuilder =
- parts.foldLeft(new StringBuilder)((s, p) => s ++= sep ++= p)
def emitDir(e: Port, isTop: Boolean): String =
if (isTop) (if (e.id.isFlip) "input " else "output ")
else (if (e.id.isFlip) "flip " else "")
@@ -1198,17 +1136,15 @@ class Emitter {
def emit(e: Arg): String = e.fullname
def emitPort(e: Port, isTop: Boolean): String =
s"${emitDir(e, isTop)}${Builder.globalRefMap.getRefForId(e.id).name} : ${emitType(e.kind)}"
- def emitType(e: Kind): String = {
- e match {
- case e: UnknownType => "?"
- case e: UIntType => s"UInt<${e.width}>"
- case e: SIntType => s"SInt<${e.width}>"
- case e: BundleType => s"{${join(e.ports.map(x => emitPort(x, false)), ", ")}}"
- case e: VectorType => s"${emitType(e.kind)}[${e.size}]"
- case e: ClockType => s"Clock"
- }
- }
- def emit(e: Command): String = e match {
+ private def emitType(e: Kind): String = e match {
+ case e: UnknownType => "?"
+ case e: UIntType => s"UInt<${e.width}>"
+ case e: SIntType => s"SInt<${e.width}>"
+ case e: BundleType => s"{${join(e.ports.map(x => emitPort(x, false)), ", ")}}"
+ case e: VectorType => s"${emitType(e.kind)}[${e.size}]"
+ case e: ClockType => s"Clock"
+ }
+ private def emit(e: Command): String = e match {
case e: DefUInt => s"node ${e.name} = UInt<${e.width}>(${e.value})"
case e: DefSInt => s"node ${e.name} = SInt<${e.width}>(${e.value})"
case e: DefFlo => s"node ${e.name} = Flo(${e.value})"
@@ -1219,46 +1155,60 @@ class Emitter {
case e: DefMemory => s"cmem ${e.name} : ${emitType(e.kind)}[${e.size}], ${e.clock.name}";
case e: DefSeqMemory => s"smem ${e.name} : ${emitType(e.kind)}[${e.size}]";
case e: DefAccessor => s"infer accessor ${e.name} = ${emit(e.source)}[${emit(e.index)}]"
- case e: DefInstance => {
- val mod = e.id
- // update all references to the modules ports
- Builder.globalRefMap.overrideRefForId(mod.io, e.name)
- "inst " + e.name + " of " + e.module + newline + join0(e.ports.flatMap(x => initPort(x, INPUT)), newline)
- }
- case e: Conditionally => {
- val prefix = if (!e.prep.isInstanceOf[EmptyCommand]) {
- newline + emit(e.prep) + newline
- } else {
- ""
- }
- val suffix = if (!e.alt.isInstanceOf[EmptyCommand]) {
- newline + "else : " + withIndent{ newline + emit(e.alt) }
- } else {
- ""
- }
- prefix + "when " + emit(e.pred) + " : " + withIndent{ emit(e.conseq) } + suffix
- }
- case e: Begin => join0(e.body.map(x => emit(x)), newline).toString
case e: Connect => s"${emit(e.loc)} := ${emit(e.exp)}"
case e: BulkConnect => s"${emit(e.loc1)} <> ${emit(e.loc2)}"
case e: ConnectInit => s"onreset ${emit(e.loc)} := ${emit(e.exp)}"
- case e: ConnectInitIndex => s"onreset ${emit(e.loc)}[${e.index}] := ${emit(e.exp)}"
- case e: EmptyCommand => "skip"
- }
- def initPort(p: Port, dir: Direction) = {
+ case e: DefInstance => {
+ // From now on, all references to the IOs occur from within the parent
+ Builder.globalRefMap.overrideRefForId(e.id.io, e.name)
+
+ val res = new StringBuilder(s"inst ${e.name} of ${e.id.name}")
+ res ++= newline
+ for (p <- e.ports; x <- initPort(p, INPUT))
+ res ++= newline + x
+ res.toString
+ }
+
+ case w: WhenBegin =>
+ indent()
+ s"when ${emit(w.pred)} :"
+ case _: WhenElse =>
+ indent()
+ "else :"
+ case _: WhenEnd =>
+ unindent()
+ "skip"
+ }
+ private def initPort(p: Port, dir: Direction) = {
for (x <- p.id.flatten; if x.dir == dir)
yield s"${Builder.globalRefMap.getRefForId(x).fullname} := ${emit(x.makeLit(0).ref)}"
}
- def emit(e: Component): String = {
- withIndent{ "module " + e.name + " : " +
- join0(e.ports.map(x => emitPort(x, true)), newline) +
- newline + join0(e.ports.flatMap(x => initPort(x, OUTPUT)), newline) +
- newline + emit(e.body) }
+
+ private def emit(m: Component): Unit = {
+ res ++= newline + s"module ${m.name} : "
+ withIndent {
+ for (p <- m.ports)
+ res ++= newline + emitPort(p, true)
+ res ++= newline
+ for (p <- m.ports; x <- initPort(p, OUTPUT))
+ res ++= newline + x
+ res ++= newline
+ for (cmd <- m.commands)
+ res ++= newline + emit(cmd)
+ res ++= newline
+ }
}
- def emit(e: Circuit): String =
- withIndent{ "circuit " + e.main + " : " + join0(e.components.map(x => emit(x)), newline) } + newline
+
+ 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.main} : ")
+ withIndent { circuit.components foreach emit }
}
object emit {
- def apply(e: Circuit) = new Emitter().emit(e)
+ def apply(e: Circuit) = new Emitter(e).toString
}