summaryrefslogtreecommitdiff
path: root/chiselFrontend/src/main/scala
diff options
context:
space:
mode:
Diffstat (limited to 'chiselFrontend/src/main/scala')
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Assert.scala8
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Mem.scala6
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Module.scala11
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/MultiClock.scala54
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Printf.scala9
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Reg.scala5
-rw-r--r--chiselFrontend/src/main/scala/chisel3/internal/Builder.scala11
7 files changed, 90 insertions, 14 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Assert.scala b/chiselFrontend/src/main/scala/chisel3/core/Assert.scala
index 4782a845..5673e298 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Assert.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Assert.scala
@@ -51,12 +51,12 @@ object assert { // scalastyle:ignore object.name
}
def apply_impl_do(cond: Bool, line: String, message: Option[String], data: Bits*)(implicit sourceInfo: SourceInfo) {
- when (!(cond || Builder.forcedModule.reset)) {
+ when (!(cond || Builder.forcedReset)) {
message match {
case Some(str) => printf.printfWithoutReset(s"Assertion failed: $str\n at $line\n", data:_*)
case None => printf.printfWithoutReset(s"Assertion failed\n at $line\n", data:_*)
}
- pushCommand(Stop(sourceInfo, Node(Builder.forcedModule.clock), 1))
+ pushCommand(Stop(sourceInfo, Node(Builder.forcedClock), 1))
}
}
@@ -76,8 +76,8 @@ object assert { // scalastyle:ignore object.name
object stop { // scalastyle:ignore object.name
/** Terminate execution with a failure code. */
def apply(code: Int)(implicit sourceInfo: SourceInfo): Unit = {
- when (!Builder.forcedModule.reset) {
- pushCommand(Stop(sourceInfo, Node(Builder.forcedModule.clock), code))
+ when (!Builder.forcedReset) {
+ pushCommand(Stop(sourceInfo, Node(Builder.forcedClock), code))
}
}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala
index ca416b1e..a48af15a 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala
@@ -27,7 +27,7 @@ object Mem {
// TODO(twigg): Remove need for this Binding
val mem = new Mem(mt, size)
- pushCommand(DefMemory(sourceInfo, mem, mt, size)) // TODO multi-clock
+ pushCommand(DefMemory(sourceInfo, mem, mt, size))
mem
}
}
@@ -92,7 +92,7 @@ sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId wi
val port = pushCommand(
DefMemPort(sourceInfo,
- t.chiselCloneType, Node(this), dir, i.ref, Node(i._parent.get.clock))
+ t.chiselCloneType, Node(this), dir, i.ref, Node(Builder.forcedClock))
).id
// Bind each element of port to being a MemoryPort
Binding.bind(port, MemoryPortBinder(Builder.forcedModule), "Error: Fresh t")
@@ -128,7 +128,7 @@ object SyncReadMem {
// TODO(twigg): Remove need for this Binding
val mem = new SyncReadMem(mt, size)
- pushCommand(DefSeqMemory(sourceInfo, mem, mt, size)) // TODO multi-clock
+ pushCommand(DefSeqMemory(sourceInfo, mem, mt, size))
mem
}
}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala
index 3ff68772..1388fb80 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala
@@ -32,11 +32,13 @@ object Module {
Builder.readyForModuleConstr = true
val parent: Option[Module] = Builder.currentModule
val whenDepth: Int = Builder.whenDepth
+ val clockAndReset: Option[ClockAndReset] = Builder.currentClockAndReset
// Execute the module, this has the following side effects:
// - set currentModule
// - unset readyForModuleConstr
// - reset whenDepth to 0
+ // - set currentClockAndReset
val m = bc.setRefs()
m._commands.prepend(DefInvalid(childSourceInfo, m.io.ref)) // init module outputs
@@ -50,6 +52,7 @@ object Module {
}
Builder.currentModule = parent // Back to parent!
Builder.whenDepth = whenDepth
+ Builder.currentClockAndReset = clockAndReset // Back to clock and reset scope
val ports = m.computePorts
// Blackbox inherits from Module so we have to match on it first TODO fix
@@ -69,6 +72,11 @@ object Module {
}
m
}
+
+ /** Returns the implicit Clock */
+ def clock: Clock = Builder.forcedClock
+ /** Returns the implicit Reset */
+ def reset: Bool = Builder.forcedReset
}
/** Abstract base class for Modules, which behave much like Verilog modules.
@@ -156,6 +164,9 @@ extends HasId {
val clock = Port(Input(Clock()))
val reset = Port(Input(Bool()))
+ // Setup ClockAndReset
+ Builder.currentClockAndReset = Some(ClockAndReset(clock, reset))
+
private[chisel3] def addId(d: HasId) { _ids += d }
private[core] def ports: Seq[(String,Data)] = Vector(
diff --git a/chiselFrontend/src/main/scala/chisel3/core/MultiClock.scala b/chiselFrontend/src/main/scala/chisel3/core/MultiClock.scala
new file mode 100644
index 00000000..62163318
--- /dev/null
+++ b/chiselFrontend/src/main/scala/chisel3/core/MultiClock.scala
@@ -0,0 +1,54 @@
+// See LICENSE for license details.
+
+package chisel3.core
+
+import scala.language.experimental.macros
+
+import chisel3.internal._
+import chisel3.internal.Builder.pushCommand
+import chisel3.internal.firrtl._
+import chisel3.internal.sourceinfo.{SourceInfo}
+
+private[chisel3] final case class ClockAndReset(clock: Clock, reset: Bool)
+
+object withClockAndReset { // scalastyle:ignore object.name
+ /** Creates a new Clock and Reset scope
+ *
+ * @param clock the new implicit Clock
+ * @param reset the new implicit Reset
+ * @param block the block of code to run with new implicit Clock and Reset
+ * @return the result of the block
+ */
+ def apply[T](clock: Clock, reset: Bool)(block: => T): T = {
+ // Save parentScope
+ val parentScope = Builder.currentClockAndReset
+ Builder.currentClockAndReset = Some(ClockAndReset(clock, reset))
+ val res = block // execute block
+ // Return to old scope
+ Builder.currentClockAndReset = parentScope
+ res
+ }
+}
+
+object withClock { // scalastyle:ignore object.name
+ /** Creates a new Clock scope
+ *
+ * @param clock the new implicit Clock
+ * @param block the block of code to run with new implicit Clock
+ * @return the result of the block
+ */
+ def apply[T](clock: Clock)(block: => T): T =
+ withClockAndReset(clock, Module.reset)(block)
+}
+
+object withReset { // scalastyle:ignore object.name
+ /** Creates a new Reset scope
+ *
+ * @param reset the new implicit Reset
+ * @param block the block of code to run with new implicit Reset
+ * @return the result of the block
+ */
+ def apply[T](reset: Bool)(block: => T): T =
+ withClockAndReset(Module.clock, reset)(block)
+}
+
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Printf.scala b/chiselFrontend/src/main/scala/chisel3/core/Printf.scala
index 4ec13751..81210f45 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Printf.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Printf.scala
@@ -34,9 +34,8 @@ object printf { // scalastyle:ignore object.name
* reset). If your definition of reset is not the encapsulating Module's
* reset, you will need to gate this externally.
*
- * May be called outside of a Module (like defined in a function), so
- * functions using printf make the standard Module assumptions (single clock
- * and single reset).
+ * May be called outside of a Module (like defined in a function), uses
+ * whatever clock and reset are in scope.
*
* @param fmt printf format string
* @param data format string varargs containing data to print
@@ -56,13 +55,13 @@ object printf { // scalastyle:ignore object.name
* @param pable [[Printable]] to print
*/
def apply(pable: Printable)(implicit sourceInfo: SourceInfo): Unit = {
- when (!Builder.forcedModule.reset) {
+ when (!Builder.forcedReset) {
printfWithoutReset(pable)
}
}
private[chisel3] def printfWithoutReset(pable: Printable)(implicit sourceInfo: SourceInfo): Unit = {
- val clock = Builder.forcedModule.clock
+ val clock = Builder.forcedClock
pushCommand(Printf(sourceInfo, Node(clock), pable))
}
private[chisel3] def printfWithoutReset(fmt: String, data: Bits*)(implicit sourceInfo: SourceInfo): Unit =
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala
index 30abe5e5..1287ac2f 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala
@@ -68,7 +68,8 @@ object Reg {
// to resolve all use cases. If the type inferencer / implicit resolution
// system improves, this may be changed.
val x = makeType(compileOptions, t, next, init)
- val clock = Node(x._parent.get.clock) // TODO multi-clock
+ val clock = Node(Builder.forcedClock)
+ val reset = Node(Builder.forcedReset)
// Bind each element of x to being a Reg
Binding.bind(x, RegBinder(Builder.forcedModule), "Error: t")
@@ -77,7 +78,7 @@ object Reg {
pushCommand(DefReg(sourceInfo, x, clock))
} else {
Binding.checkSynthesizable(init, s"'init' ($init)")
- pushCommand(DefRegInit(sourceInfo, x, clock, Node(x._parent.get.reset), init.ref))
+ pushCommand(DefRegInit(sourceInfo, x, clock, reset, init.ref))
}
if (next != null) {
Binding.checkSynthesizable(next, s"'next' ($next)")
diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala
index 9e389788..e6e69e03 100644
--- a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala
+++ b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala
@@ -151,6 +151,7 @@ private[chisel3] class DynamicContext() {
// Used to distinguish between no Module() wrapping, multiple wrappings, and rewrapping
var readyForModuleConstr: Boolean = false
var whenDepth: Int = 0 // Depth of when nesting
+ var currentClockAndReset: Option[ClockAndReset] = None
val errors = new ErrorLog
val namingStack = new internal.naming.NamingStack
}
@@ -186,6 +187,16 @@ private[chisel3] object Builder {
def whenDepth_=(target: Int): Unit = {
dynamicContext.whenDepth = target
}
+ def currentClockAndReset: Option[ClockAndReset] = dynamicContext.currentClockAndReset
+ def currentClockAndReset_=(target: Option[ClockAndReset]): Unit = {
+ dynamicContext.currentClockAndReset = target
+ }
+ def forcedClockAndReset: ClockAndReset = currentClockAndReset match {
+ case Some(clockAndReset) => clockAndReset
+ case None => throwException("Error: No implicit clock and reset.")
+ }
+ def forcedClock: Clock = forcedClockAndReset.clock
+ def forcedReset: Bool = forcedClockAndReset.reset
// TODO(twigg): Ideally, binding checks and new bindings would all occur here
// However, rest of frontend can't support this yet.