summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHenry Cook2015-08-03 19:28:50 -0700
committerHenry Cook2015-08-03 19:39:24 -0700
commit8e856389bd4a11f7d9a269faf32b47b5afc61a70 (patch)
tree5ec84a1ce3d64108db6197993e26da8f889d9b3e /src
parentbf72a6a7fd747a267d4264ac2d532bb02407f7c6 (diff)
Improve type-safety of switch/is blocks using macros and SwitchContext. Removed switch key stack.
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/Chisel/Core.scala12
-rw-r--r--src/main/scala/Chisel/utils.scala39
2 files changed, 25 insertions, 26 deletions
diff --git a/src/main/scala/Chisel/Core.scala b/src/main/scala/Chisel/Core.scala
index d9d7cf38..a3483c82 100644
--- a/src/main/scala/Chisel/Core.scala
+++ b/src/main/scala/Chisel/Core.scala
@@ -16,14 +16,6 @@ class IdGen {
object Builder {
val components = new ArrayBuffer[Component]()
val idGen = new IdGen
- val switchKeyz = new Stack[Stack[Bits]]()
- def switchKeys = switchKeyz.top
- def pushScope = {
- switchKeyz.push(new Stack[Bits]())
- }
- def popScope = {
- switchKeyz.pop()
- }
val modulez = new Stack[Module]()
def pushModule(mod: Module) {
modulez.push(mod)
@@ -993,7 +985,6 @@ object Module {
val m = bc
m.setRefs
val cmd = popCommands
- popScope
popModule
val ports = m.computePorts
val component = Component(m.name, ports, cmd)
@@ -1017,7 +1008,6 @@ abstract class Module(_clock: Clock = null, _reset: Bool = null) extends Id {
val name = globalNamespace.name(getClass.getName.split('.').last)
pushModule(this)
- pushScope
pushCommands
val params = Module.params
@@ -1091,11 +1081,9 @@ abstract class BlackBox(_clock: Clock = null, _reset: Bool = null) extends Modul
object when {
private[Chisel] def execBlock(block: => Unit): Command = {
- pushScope
pushCommands
block
val cmd = popCommands
- popScope
cmd
}
def apply(cond: => Bool)(block: => Unit): when = {
diff --git a/src/main/scala/Chisel/utils.scala b/src/main/scala/Chisel/utils.scala
index 1e024b11..6d073e3d 100644
--- a/src/main/scala/Chisel/utils.scala
+++ b/src/main/scala/Chisel/utils.scala
@@ -1,6 +1,10 @@
package Chisel
import Builder._
import scala.math._
+import scala.language.reflectiveCalls
+import scala.language.experimental.macros
+import scala.reflect.runtime.universe._
+import scala.reflect.macros.whitebox._
object log2Up
{
@@ -122,23 +126,30 @@ object unless {
}
}
-object switch {
- def apply(c: Bits)(block: => Unit) {
- switchKeys.push(c)
- block
- switchKeys.pop()
+class SwitchContext[T <: Bits](cond: T) {
+ def is(v: Iterable[T])(block: => Unit) {
+ if (!v.isEmpty) when (v.map(_.asUInt === cond.asUInt).reduce(_||_)) { block }
}
+ def is(v: T)(block: => Unit) { is(Seq(v))(block) }
+ def is(v: T, vr: T*)(block: => Unit) { is(v :: vr.toList)(block) }
+}
+
+object is { // Begin deprecation of non-type-parameterized is statements.
+ def apply(v: Iterable[Bits])(block: => Unit) { ChiselError.error("The 'is' keyword may not be used outside of a switch.") }
+ def apply(v: Bits)(block: => Unit) { ChiselError.error("The 'is' keyword may not be used outside of a switch.") }
+ def apply(v: Bits, vr: Bits*)(block: => Unit) { ChiselError.error("The 'is' keyword may not be used outside of a switch.") }
}
-object is {
- def apply(v: Bits)(block: => Unit): Unit =
- apply(Seq(v))(block)
- def apply(v: Bits, vr: Bits*)(block: => Unit): Unit =
- apply(v :: vr.toList)(block)
- def apply(v: Iterable[Bits])(block: => Unit): Unit = {
- val keys = switchKeys
- if (keys.isEmpty) ChiselError.error("The 'is' keyword may not be used outside of a switch.")
- else if (!v.isEmpty) when (v.map(_.toBits === keys.top.toBits).reduce(_||_)) { block }
+object switch {
+ def apply[T <: Bits](cond: T)(x: => Unit): Unit = macro impl
+ def impl(c: Context)(cond: c.Tree)(x: c.Tree) = { import c.universe._
+ def extractIsStatement(tree: Tree): List[c.universe.Tree] = tree match {
+ case q"Chisel.is.apply( ..$params )( ..$body )" => List(q"sc.is( ..$params )( ..$body )")
+ case b => throw new Exception(s"Cannot include blocks that do not begin with is() in switch.")
+ }
+ val q"..$body" = x
+ val ises = body.flatMap(extractIsStatement(_))
+ q"""{ val sc = new SwitchContext($cond); ..$ises }"""
}
}