summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md5
-rw-r--r--src/main/scala/Chisel/util/Arbiter.scala104
-rw-r--r--src/main/scala/Chisel/util/Counter.scala4
-rw-r--r--src/main/scala/Chisel/util/Decoupled.scala25
-rw-r--r--src/main/scala/Chisel/util/OneHot.scala6
5 files changed, 86 insertions, 58 deletions
diff --git a/README.md b/README.md
index 4d7f599f..956f5a4c 100644
--- a/README.md
+++ b/README.md
@@ -139,6 +139,11 @@ This will walk you through installing Chisel and its dependencies:
sudo make install
```
+### Arch Linux
+ ```
+ yaourt -S firrtl-git verilator sbt
+ ```
+
### Windows
*TODO: write me. If you __really__ want to see this happen, let us know by filing a bug report!*
diff --git a/src/main/scala/Chisel/util/Arbiter.scala b/src/main/scala/Chisel/util/Arbiter.scala
index 2747640f..16ae9be5 100644
--- a/src/main/scala/Chisel/util/Arbiter.scala
+++ b/src/main/scala/Chisel/util/Arbiter.scala
@@ -13,75 +13,69 @@ class ArbiterIO[T <: Data](gen: T, n: Int) extends Bundle {
}
/** Arbiter Control determining which producer has access */
-object ArbiterCtrl
+private object ArbiterCtrl
{
- def apply(request: Seq[Bool]): Seq[Bool] = {
- Bool(true) +: (1 until request.length).map(i => !request.slice(0, i).foldLeft(Bool(false))(_ || _))
+ def apply(request: Seq[Bool]): Seq[Bool] = request.length match {
+ case 0 => Seq()
+ case 1 => Seq(Bool(true))
+ case _ => Bool(true) +: request.tail.init.scanLeft(request.head)(_ || _).map(!_)
}
}
-abstract class LockingArbiterLike[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool] = None)
- extends Module {
- require(isPow2(count))
+abstract class LockingArbiterLike[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool]) extends Module {
def grant: Seq[Bool]
+ def choice: UInt
val io = new ArbiterIO(gen, n)
- val locked = if(count > 1) Reg(init=Bool(false)) else Bool(false)
- val lockIdx = if(count > 1) Reg(init=UInt(n-1)) else UInt(n-1)
- val chosen = Wire(UInt(width = log2Up(n)))
-
- io.out.valid := io.in(chosen).valid
- io.out.bits := io.in(chosen).bits
- io.chosen := chosen
-
- io.in(chosen).ready := Bool(false) // XXX FIRRTL workaround
- for ((g, i) <- grant.zipWithIndex)
- io.in(i).ready := Mux(locked, lockIdx === UInt(i), g) && io.out.ready
-
- if(count > 1){
- val cnt = Reg(init=UInt(0, width = log2Up(count)))
- val cnt_next = cnt + UInt(1)
- when(io.out.fire()) {
- when(needsLock.map(_(io.out.bits)).getOrElse(Bool(true))) {
- cnt := cnt_next
- when(!locked) {
- locked := Bool(true)
- lockIdx := Vec(io.in.map{ in => in.fire()}).indexWhere{i: Bool => i}
- }
- }
- when(cnt_next === UInt(0)) {
- locked := Bool(false)
- }
+
+ io.chosen := choice
+ io.out.valid := io.in(io.chosen).valid
+ io.out.bits := io.in(io.chosen).bits
+
+ if (count > 1) {
+ val lockCount = Counter(count)
+ val lockIdx = Reg(UInt())
+ val locked = lockCount.value =/= UInt(0)
+ val wantsLock = needsLock.map(_(io.out.bits)).getOrElse(Bool(true))
+
+ when (io.out.fire() && wantsLock) {
+ lockIdx := io.chosen
+ lockCount.inc()
}
+
+ when (locked) { io.chosen := lockIdx }
+ for ((in, (g, i)) <- io.in zip grant.zipWithIndex)
+ in.ready := Mux(locked, lockIdx === UInt(i), g) && io.out.ready
+ } else {
+ for ((in, g) <- io.in zip grant)
+ in.ready := g && io.out.ready
}
}
class LockingRRArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool] = None)
extends LockingArbiterLike[T](gen, n, count, needsLock) {
- lazy val last_grant = Reg(init=UInt(0, log2Up(n)))
+ lazy val lastGrant = RegEnable(io.chosen, io.out.fire())
+ lazy val grantMask = (0 until n).map(UInt(_) > lastGrant)
+ lazy val validMask = io.in zip grantMask map { case (in, g) => in.valid && g }
+
override def grant: Seq[Bool] = {
- val ctrl = ArbiterCtrl((0 until n).map(i => io.in(i).valid && UInt(i) > last_grant) ++ io.in.map(_.valid))
- (0 until n).map(i => ctrl(i) && UInt(i) > last_grant || ctrl(i + n))
+ val ctrl = ArbiterCtrl((0 until n).map(i => validMask(i)) ++ io.in.map(_.valid))
+ (0 until n).map(i => ctrl(i) && grantMask(i) || ctrl(i + n))
}
- var choose = UInt(n-1)
+ override lazy val choice = Wire(init=UInt(n-1))
for (i <- n-2 to 0 by -1)
- choose = Mux(io.in(i).valid, UInt(i), choose)
+ when (io.in(i).valid) { choice := UInt(i) }
for (i <- n-1 to 1 by -1)
- choose = Mux(io.in(i).valid && UInt(i) > last_grant, UInt(i), choose)
- chosen := Mux(locked, lockIdx, choose)
-
- when (io.out.fire()) { last_grant := chosen }
+ when (validMask(i)) { choice := UInt(i) }
}
class LockingArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool] = None)
extends LockingArbiterLike[T](gen, n, count, needsLock) {
def grant: Seq[Bool] = ArbiterCtrl(io.in.map(_.valid))
- var choose = UInt(n-1)
- for (i <- n-2 to 0 by -1) {
- choose = Mux(io.in(i).valid, UInt(i), choose)
- }
- chosen := Mux(locked, lockIdx, choose)
+ override lazy val choice = Wire(init=UInt(n-1))
+ for (i <- n-2 to 0 by -1)
+ when (io.in(i).valid) { choice := UInt(i) }
}
/** Hardware module that is used to sequence n producers into 1 consumer.
@@ -104,4 +98,20 @@ class RRArbiter[T <: Data](gen:T, n: Int) extends LockingRRArbiter[T](gen, n, 1)
arb.io.in(1) <> producer1.io.out
consumer.io.in <> arb.io.out
*/
-class Arbiter[T <: Data](gen: T, n: Int) extends LockingArbiter[T](gen, n, 1)
+class Arbiter[T <: Data](gen: T, n: Int) extends Module {
+ val io = new ArbiterIO(gen, n)
+
+ io.chosen := UInt(n-1)
+ io.out.bits := io.in(n-1).bits
+ for (i <- n-2 to 0 by -1) {
+ when (io.in(i).valid) {
+ io.chosen := UInt(i)
+ io.out.bits := io.in(i).bits
+ }
+ }
+
+ val grant = ArbiterCtrl(io.in.map(_.valid))
+ for ((in, g) <- io.in zip grant)
+ in.ready := g && io.out.ready
+ io.out.valid := !grant.last || io.in.last.valid
+}
diff --git a/src/main/scala/Chisel/util/Counter.scala b/src/main/scala/Chisel/util/Counter.scala
index 3425b6a2..14f51ec4 100644
--- a/src/main/scala/Chisel/util/Counter.scala
+++ b/src/main/scala/Chisel/util/Counter.scala
@@ -17,7 +17,9 @@ class Counter(val n: Int) {
Bool(true)
} else {
val wrap = value === UInt(n-1)
- value := Mux(Bool(!isPow2(n)) && wrap, UInt(0), value + UInt(1))
+ value := value + UInt(1)
+ if (!isPow2(n))
+ when (wrap) { value := UInt(0) }
wrap
}
}
diff --git a/src/main/scala/Chisel/util/Decoupled.scala b/src/main/scala/Chisel/util/Decoupled.scala
index ba33e6c7..498af572 100644
--- a/src/main/scala/Chisel/util/Decoupled.scala
+++ b/src/main/scala/Chisel/util/Decoupled.scala
@@ -116,11 +116,9 @@ class Queue[T <: Data](gen: T, val entries: Int,
val ptr_match = enq_ptr.value === deq_ptr.value
val empty = ptr_match && !maybe_full
val full = ptr_match && maybe_full
- val maybe_flow = Bool(flow) && empty
- val do_flow = maybe_flow && io.deq.ready
+ val do_enq = Wire(init=io.enq.fire())
+ val do_deq = Wire(init=io.deq.fire())
- val do_enq = io.enq.ready && io.enq.valid && !do_flow
- val do_deq = io.deq.ready && io.deq.valid && !do_flow
when (do_enq) {
ram(enq_ptr.value) := io.enq.bits
enq_ptr.inc()
@@ -132,9 +130,22 @@ class Queue[T <: Data](gen: T, val entries: Int,
maybe_full := do_enq
}
- io.deq.valid := !empty || Bool(flow) && io.enq.valid
- io.enq.ready := !full || Bool(pipe) && io.deq.ready
- io.deq.bits := Mux(maybe_flow, io.enq.bits, ram(deq_ptr.value))
+ io.deq.valid := !empty
+ io.enq.ready := !full
+ io.deq.bits := ram(deq_ptr.value)
+
+ if (flow) {
+ when (io.enq.valid) { io.deq.valid := Bool(true) }
+ when (empty) {
+ io.deq.bits := io.enq.bits
+ do_deq := Bool(false)
+ when (io.deq.ready) { do_enq := Bool(false) }
+ }
+ }
+
+ if (pipe) {
+ when (io.deq.ready) { io.enq.ready := Bool(true) }
+ }
val ptr_diff = enq_ptr.value - deq_ptr.value
if (isPow2(entries)) {
diff --git a/src/main/scala/Chisel/util/OneHot.scala b/src/main/scala/Chisel/util/OneHot.scala
index 38b96511..73f27403 100644
--- a/src/main/scala/Chisel/util/OneHot.scala
+++ b/src/main/scala/Chisel/util/OneHot.scala
@@ -51,12 +51,12 @@ object UIntToOH
object PriorityEncoderOH
{
private def encode(in: Seq[Bool]): UInt = {
- val outs = Vec.tabulate(in.size)(i => UInt(BigInt(1) << i, in.size))
+ val outs = Seq.tabulate(in.size)(i => UInt(BigInt(1) << i, in.size))
PriorityMux(in :+ Bool(true), outs :+ UInt(0, in.size))
}
- def apply(in: Seq[Bool]): Vec[Bool] = {
+ def apply(in: Seq[Bool]): Seq[Bool] = {
val enc = encode(in)
- Vec.tabulate(in.size)(enc(_))
+ Seq.tabulate(in.size)(enc(_))
}
def apply(in: Bits): UInt = encode((0 until in.getWidth).map(i => in(i)))
}