summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/scala/Core.scala240
-rw-r--r--src/main/scala/FP.scala4
-rw-r--r--src/main/scala/Tester.scala2
-rw-r--r--src/main/scala/utils.scala154
4 files changed, 248 insertions, 152 deletions
diff --git a/src/main/scala/Core.scala b/src/main/scala/Core.scala
index d41f3081..7145ccaa 100644
--- a/src/main/scala/Core.scala
+++ b/src/main/scala/Core.scala
@@ -1,15 +1,17 @@
package Chisel
-import scala.collection.mutable.{ArrayBuffer, Stack, HashSet, HashMap}
+import scala.collection.mutable.{ArrayBuffer, Stack, HashSet, HashMap, LinkedHashMap}
import java.lang.reflect.Modifier._
import java.lang.Double.longBitsToDouble
import java.lang.Float.intBitsToFloat
class GenSym {
- var counter = -1
- def next(name: String): String = {
+ private var counter = -1
+ def nextInt: Int = {
counter += 1
- name + "_" + counter
+ counter
}
+ def next(name: String): String =
+ name + "_" + nextInt
}
object Builder {
@@ -278,7 +280,9 @@ import Direction._
/// CHISEL FRONT-END
abstract class Id {
- protected[Chisel] val cid = genSym.next("id")
+ protected[Chisel] val _id = genSym.nextInt
+ protected[Chisel] val cid = "id_" + _id
+
var isDef_ = false
def defd: this.type = {
isDef_ = true
@@ -332,15 +336,14 @@ abstract class Data(dirArg: Direction) extends Id {
def setLitValue(x: LitArg) { }
def floLitValue: Float = intBitsToFloat(litValue().toInt)
def dblLitValue: Double = longBitsToDouble(litValue().toLong)
- def getWidth: Int
+ def getWidth: Int = flatten.map(_.getWidth).reduce(_ + _)
def maxWidth(other: Data, amt: BigInt): Int = -1
def sumWidth(amt: BigInt): Int = -1
def sumWidth(other: Data, amt: BigInt): Int = -1
- def flatten: Array[Bits]
+ def flatten: IndexedSeq[Bits]
def fromBits(n: Bits): this.type = {
- val res = this.cloneType
var i = 0
- val wire = Wire(res)
+ val wire = Wire(this.cloneType)
for (x <- wire.flatten.reverse) {
x := n(i + x.getWidth-1, i)
i += x.getWidth
@@ -351,14 +354,10 @@ abstract class Data(dirArg: Direction) extends Id {
val elts = this.flatten.reverse
Cat(elts.head, elts.tail:_*).asUInt
}
- def makeLit(value: BigInt, width: Int): this.type = {
- val x = cloneType
- x.fromBits(Bits(value, width))
- x
- }
+ def makeLit(value: BigInt, width: Int): this.type =
+ this.fromBits(Bits(value, width))
def toPort: Port = Port(cid, dir, toType)
- def collectElts: Unit
var isReg_ = false
def isReg = isReg_
def params = if(Driver.parStack.isEmpty) Parameters.empty else Driver.parStack.top
@@ -371,7 +370,6 @@ object Wire {
throw new Exception("cannot infer type of Init.")
val x = mType.cloneType
// TODO: COME UP WITH MORE ROBUST WAY TO HANDLE THIS
- x.collectElts
pushCommand(DefWire(x.defd.cid, x.toType))
if (init != null)
pushCommand(Connect(x.lref, init.ref))
@@ -409,7 +407,9 @@ object Mem {
}
}
-class Mem[T <: Data](val t: T, val n: Int) /* with VecLike[T] */ { // TODO: VECLIKE
+class Mem[T <: Data](protected[Chisel] val t: T, n: Int) extends VecLike[T] {
+ def length: Int = n
+ def apply(idx: Int): T = apply(UInt(idx))
def apply(idx: UInt): T = {
val x = t.cloneType
pushCommand(DefAccessor(x.defd.cid, Alias(t.cid), NO_DIR, idx.ref))
@@ -418,32 +418,30 @@ class Mem[T <: Data](val t: T, val n: Int) /* with VecLike[T] */ { // TODO: VEC
def read(idx: UInt): T = apply(idx)
def write(idx: UInt, data: T): Unit = apply(idx) := data
+ def write(idx: UInt, data: T, mask: T): Unit = {
+ // This is totally fucked, but there's no true write mask support yet
+ val mask1 = mask.toBits
+ write(idx, t.fromBits((read(idx).toBits & ~mask1) | (data.toBits & mask1)))
+ }
def name = getRefForId(t.cid).name
def debugName = t.mod.debugName + "." + getRefForId(t.cid).debugName
}
object SeqMem {
- def apply[T <: Data](t: T, size: Int): SeqMem[T] = {
- val mt = t.cloneType
- val mem = new SeqMem(mt, size)
- pushCommand(DefSeqMemory(mt.defd.cid, mt.toType, size))
- mem
- }
+ def apply[T <: Data](t: T, size: Int): SeqMem[T] =
+ new SeqMem(t, size)
}
-class SeqMem[T <: Data](val t: T, val n: Int) /* with VecLike[T] */ { // TODO: VECLIKE
- def apply(idx: UInt): T = {
- val x = t.cloneType
- pushCommand(DefAccessor(x.defd.cid, Alias(t.cid), NO_DIR, idx.ref))
- x
- }
+// For now, implement SeqMem in terms of Mem
+class SeqMem[T <: Data](t: T, n: Int) {
+ private val mem = Mem(t, n)
- def read(idx: UInt): T = apply(idx)
- def write(idx: UInt, data: T): Unit = apply(idx) := data
+ def read(addr: UInt): T = mem.read(Reg(next = addr))
+ def read(addr: UInt, enable: Bool): T = mem.read(RegEnable(addr, enable))
- def name = getRefForId(t.cid).name
- def debugName = t.mod.debugName + "." + getRefForId(t.cid).debugName
+ def write(addr: UInt, data: T): Unit = mem.write(addr, data)
+ def write(addr: UInt, data: T, mask: T): Unit = mem.write(addr, data, mask)
}
object Vec {
@@ -451,7 +449,6 @@ object Vec {
new Vec((0 until n).map(i => gen.cloneType))
def apply[T <: Data](elts: Iterable[T]): Vec[T] = {
val vec = new Vec[T](elts.map(e => elts.head.cloneType))
- vec.collectElts
val isDef = true || elts.head.isDef
if (vec.isReg)
throw new Exception("Vec of Reg Deprecated.")
@@ -474,17 +471,23 @@ object Vec {
}
abstract class Aggregate(dirArg: Direction) extends Data(dirArg) {
- def cloneTypeWidth(width: Int): this.type = {
- val res = cloneType
- res.collectElts
- res
- }
+ def cloneTypeWidth(width: Int): this.type = cloneType
}
-class Vec[T <: Data](val elts: Iterable[T], dirArg: Direction = NO_DIR) extends Aggregate(dirArg) with VecLike[T] {
- val elt0 = elts.head
- val self = new ArrayBuffer[T]()
- self ++= elts
+class Vec[T <: Data](elts: Iterable[T], dirArg: Direction = NO_DIR) extends Aggregate(dirArg) with VecLike[T] {
+ private val self = elts.toIndexedSeq
+ private val elt0 = elts.head
+
+ // println("BEGIN VEC NAMING")
+ for ((e, i) <- self zipWithIndex) {
+ // println(" NAME " + i + " -> " + cid)
+ setIndexForId(cid, e.cid, i)
+ }
+ // println("DONE VEC NAMING")
+
+ def <> (that: Iterable[T]): Unit =
+ this <> Vec(that).asInstanceOf[Data]
+
override def isReg = elt0.isReg
override def isFlip = {
val isSubFlip = elt0.isFlip
@@ -493,7 +496,6 @@ class Vec[T <: Data](val elts: Iterable[T], dirArg: Direction = NO_DIR) extends
def apply(idx: UInt): T = {
val x = elt0.cloneType
- x.collectElts
pushCommand(DefAccessor(x.defd.cid, Alias(cid), NO_DIR, idx.ref))
x
}
@@ -503,15 +505,10 @@ class Vec[T <: Data](val elts: Iterable[T], dirArg: Direction = NO_DIR) extends
self.map(d => d.toPort).toArray
def toType: Kind =
VectorType(self.size, elt0.toType, isFlipVar)
- override def cloneType: this.type = {
- val v = Vec(elt0.cloneType, self.size).asInstanceOf[this.type]
- v.collectElts
- v
- }
- override def init(dummy:Int = 0) = {
- collectElts
+ override def cloneType: this.type =
+ Vec(elt0.cloneType, self.size).asInstanceOf[this.type]
+ override def init(dummy:Int = 0) =
for (e <- self) e.init()
- }
def inits (f: (Int, T, (Int, T, T) => Unit) => Unit) = {
var i = 0
def doInit (index: Int, elt: T, init: T) =
@@ -521,18 +518,8 @@ class Vec[T <: Data](val elts: Iterable[T], dirArg: Direction = NO_DIR) extends
i += 1;
}
}
- override def flatten: Array[Bits] =
+ override def flatten: IndexedSeq[Bits] =
self.map(_.flatten).reduce(_ ++ _)
- override def getWidth: Int =
- flatten.map(_.getWidth).reduce(_ + _)
-
- def collectElts: Unit = {
- for (i <- 0 until self.size) {
- val elt = self(i)
- setIndexForId(cid, elt.cid, i)
- elt.collectElts
- }
- }
def length: Int = self.size
@@ -569,12 +556,11 @@ import Literal._
class BitPat(val value: String, val width: Int) extends Data(NO_DIR) {
def cloneTypeWidth(width: Int): this.type = cloneType
- def collectElts: Unit = { }
override def dir: Direction = NO_DIR
override def setDir(dir: Direction): Unit = { }
override def toType: Kind = UIntType(UnknownWidth(), isFlip)
override def getWidth: Int = width
- override def flatten: Array[Bits] = Array[Bits](Bits(0))
+ override def flatten: IndexedSeq[Bits] = throw new Exception("BitPat.flatten")
override def cloneType: this.type =
new BitPat(value, width).asInstanceOf[this.type]
def fromInt(x: BigInt): BitPat = BitPat(x.toString(2), -1).asInstanceOf[this.type]
@@ -595,7 +581,6 @@ object BitPat {
}
abstract class Element(dirArg: Direction, val width: Int) extends Data(dirArg) {
- def collectElts: Unit = { }
override def getWidth: Int = width
}
@@ -609,7 +594,7 @@ abstract class Bits(dirArg: Direction, width: Int) extends Element(dirArg, width
override def cloneType : this.type = cloneTypeWidth(width)
def fromInt(x: BigInt): this.type = makeLit(x, -1)
- override def flatten: Array[Bits] = Array[Bits](this)
+ override def flatten: IndexedSeq[Bits] = IndexedSeq(this)
final def apply(x: BigInt): Bool = {
val d = new Bool(dir)
@@ -650,12 +635,6 @@ abstract class Bits(dirArg: Direction, width: Int) extends Element(dirArg, width
def :=(other: Bits) =
pushCommand(Connect(this.lref, other.ref))
- override def fromBits(n: Bits): this.type = {
- val res = Wire(this.cloneType)
- res := n
- res.asInstanceOf[this.type]
- }
-
protected[Chisel] def unop(op: PrimOp, width: Int): this.type = {
val d = cloneTypeWidth(width)
pushCommand(DefPrim(d.defd.cid, d.toType, op, Array(this.ref), NoLits))
@@ -720,7 +699,7 @@ abstract class Bits(dirArg: Direction, width: Int) extends Element(dirArg, width
def andR = (this === Bits(-1))
def xorR = bits_redop(XorReduceOp)
- def bitSet(off: BigInt, dat: Bits): Bits = {
+ def bitSet(off: UInt, dat: Bits): Bits = {
val bit = UInt(1, 1) << off
this & ~bit | dat.toSInt & bit
}
@@ -812,7 +791,7 @@ class UInt(dir: Direction, width: Int) extends Bits(dir, width) with Num[UInt] {
}
def asSInt(): SInt = {
- val x = SInt(width = getWidth + 1)
+ val x = SInt(width = getWidth)
pushCommand(DefPrim(x.defd.cid, x.toType, AsSIntOp, Array(ref), NoLits))
x
}
@@ -881,6 +860,7 @@ class SInt(dir: Direction, width: Int) extends Bits(dir, width) with Num[SInt] {
def != (other: SInt): Bool = compop(NotEqualOp, other)
def <= (other: SInt): Bool = compop(LessEqOp, other)
def >= (other: SInt): Bool = compop(GreaterEqOp, other)
+ def abs: UInt = Mux(this < SInt(0), (-this).toUInt, this.toUInt)
override def pad (other: BigInt): SInt = binop(PadOp, other, other.toInt)
@@ -941,31 +921,12 @@ object Bool {
object Mux {
def apply[T <: Data](cond: Bool, con: T, alt: T): T = {
- def genericMux[T <: Data](cond: Bool, con: T, alt: T): T = {
- val w = Wire(alt, init = alt)
- when (cond) {
- w := con
- }
- w
- }
- con match {
- case tc: Bits =>
- alt match {
- case ta: Bits =>
- if (tc.isInstanceOf[UInt] != ta.isInstanceOf[UInt])
- error("Unable to have mixed type mux CON " + con + " ALT " + alt)
- // println("MUX COND " + cond + " CON(" + con.litValue() + ")'" + con.getWidth + " " + con + " ALT(" + alt.litValue() + ")'" + alt.getWidth + " " + alt)
- val rb = tc.cloneTypeWidth(tc.maxWidth(ta, 0))
- pushCommand(DefPrim(rb.defd.cid, rb.toType, MultiplexOp, Array(cond.ref, tc.ref, ta.ref), NoLits))
- rb.asInstanceOf[T]
- case _ =>
- genericMux(cond, con, alt)
- }
- case _ =>
- genericMux(cond, con, alt)
+ val w = Wire(alt, init = alt)
+ when (cond) {
+ w := con
}
+ w
}
-
}
object Cat {
@@ -995,7 +956,8 @@ object Cat {
object Bundle {
val keywords = HashSet[String]("elements", "flip", "toString",
"flatten", "binding", "asInput", "asOutput", "unary_$tilde",
- "unary_$bang", "unary_$minus", "cloneType", "toUInt", "toBits",
+ "unary_$bang", "unary_$minus", "cloneType",
+ "toUInt", "toBits",
"toBool", "toSInt", "asDirectionless")
def apply[T <: Bundle](b: => T)(implicit p: Parameters): T = {
Driver.parStack.push(p.push)
@@ -1010,74 +972,67 @@ object Bundle {
private def params = if(Driver.parStack.isEmpty) Parameters.empty else Driver.parStack.top
}
-class Bundle(dirArg: Direction = NO_DIR) extends Aggregate(dirArg) {
+trait BundleFinalizer extends DelayedInit {
+ def collectElts = { }
+ def delayedInit(body: => Unit) = {
+ body // evaluates the initialization code of C
+ collectElts
+ }
+}
+
+class Bundle(dirArg: Direction = NO_DIR) extends Aggregate(dirArg) with BundleFinalizer {
def toPorts: Array[Port] =
- elts.map(d => d.toPort).toArray
+ elements.map(_._2.toPort).toArray
def toType: BundleType =
BundleType(this.toPorts, isFlipVar)
- override def flatten: Array[Bits] = {
- collectElts
- elts.map(_.flatten).reduce(_ ++ _)
+ override def flatten: IndexedSeq[Bits] = {
+ val sortedElts = elements.values.toIndexedSeq sortWith (_._id < _._id)
+ sortedElts.map(_.flatten).reduce(_ ++ _)
}
- override def getWidth: Int =
- flatten.map(_.getWidth).reduce(_ + _)
- val elts = ArrayBuffer[Data]()
- override def init(dummy:Int = 0) = {
- collectElts
- for (e <- elts) e.init()
- }
- def collectElts: Unit = {
- elts.clear()
+ override def init(dummy:Int = 0) =
+ for ((s, e) <- elements) e.init()
+ lazy val elements: LinkedHashMap[String, Data] = {
+ val elts = LinkedHashMap[String, Data]()
+ // println("BEGIN BUNDLE NAMING " + cid)
for (m <- getClass.getMethods) {
val name = m.getName
-
- val modifiers = m.getModifiers();
- val types = m.getParameterTypes()
- var isInterface = false;
- var isFound = false;
- val rtype = m.getReturnType();
- var c = rtype;
- val sc = Class.forName("Chisel.Data");
- do {
- if (c == sc) {
- isFound = true; isInterface = true;
- } else if (c == null || c == Class.forName("java.lang.Object")) {
- isFound = true; isInterface = false;
- } else {
- c = c.getSuperclass();
- }
- } while (!isFound);
- if (types.length == 0 && !isStatic(modifiers) && isInterface
- && !(Bundle.keywords contains name)) {
+ // println("NAME = " + name)
+ val rtype = m.getReturnType
+ val isInterface = classOf[Data].isAssignableFrom(rtype)
+ if (m.getParameterTypes.isEmpty &&
+ !isStatic(m.getModifiers) &&
+ isInterface &&
+ !(Bundle.keywords contains name)) {
val obj = m.invoke(this)
obj match {
case data: Data =>
+ // println(" NAMING " + name + " -> " + cid)
setFieldForId(cid, data.cid, name)
- data.collectElts
- elts += data
+ elts(name) = data
case _ => ()
}
}
}
-
- elts.sortWith { (a, b) => a.cid < b.cid }
+ // println("DONE BUNDLE NAMING " + cid)
+ elts
}
+ override def collectElts = elements
override def cloneType : this.type = {
try {
val constructor = this.getClass.getConstructors.head
val res = constructor.newInstance(Array.fill(constructor.getParameterTypes.size)(null):_*)
- val rest = res.asInstanceOf[this.type]
- rest.collectElts
- rest
+ res.asInstanceOf[this.type]
} catch {
case npe: java.lang.reflect.InvocationTargetException if npe.getCause.isInstanceOf[java.lang.NullPointerException] =>
// throwException("Parameterized Bundle " + this.getClass + " needs cloneType method. You are probably using an anonymous Bundle object that captures external state and hence is un-cloneTypeable", npe)
- error("BAD")
+ val s = "CLONE INVOKATION EXCEPTION " + this.getClass
+ error(s)
case e: java.lang.Exception =>
- error("BAD")
+ val s = "CLONE EXCEPTION " + this.getClass
+ error(s)
// throwException("Parameterized Bundle " + this.getClass + " needs cloneType method", e)
}
}
@@ -1091,7 +1046,6 @@ object Module {
val cmd = popCommands
popScope
popModule
- m.io.collectElts
m.setRefs
val ports = m.io.toPorts
val component = UniqueComponent(m.name, ports, cmd)
@@ -1151,8 +1105,6 @@ abstract class Module(private[Chisel] _reset: Bool = null) extends Id {
}
case mem: Mem[_] =>
setRefForId(mem.t.cid, name)
- case mem: SeqMem[_] =>
- setRefForId(mem.t.cid, name)
case vec: Vec[_] =>
setRefForId(vec.cid, name)
case data: Data =>
diff --git a/src/main/scala/FP.scala b/src/main/scala/FP.scala
index 7f2615f3..f7bbaae5 100644
--- a/src/main/scala/FP.scala
+++ b/src/main/scala/FP.scala
@@ -94,7 +94,7 @@ class Flo(dir: Direction = NO_DIR, val value:Option[Float] = None) extends Eleme
}
def toType: Kind = FloType(isFlip)
def cloneType: this.type = new Flo(dir).asInstanceOf[this.type]
- def flatten: Array[Bits] = Array[Bits](toBits)
+ def flatten: IndexedSeq[Bits] = IndexedSeq(toBits)
def fromInt(x: Int): Flo =
Flo(x.toFloat).asInstanceOf[this.type]
@@ -209,7 +209,7 @@ class Dbl(dir: Direction, val value: Option[Double] = None) extends Element(dir,
}
def toType: Kind = DblType(isFlip)
def cloneType: this.type = new Dbl(dir).asInstanceOf[this.type]
- def flatten: Array[Bits] = Array[Bits](toBits)
+ def flatten: IndexedSeq[Bits] = IndexedSeq(toBits)
def fromInt(x: Int): this.type =
Dbl(x.toDouble).asInstanceOf[this.type]
diff --git a/src/main/scala/Tester.scala b/src/main/scala/Tester.scala
index 68fad15d..bdeb0f68 100644
--- a/src/main/scala/Tester.scala
+++ b/src/main/scala/Tester.scala
@@ -215,7 +215,7 @@ class ManualTester[+T <: Module]
longBitsToDouble(peekBits(data).toLong)
}
- def peek(data: Aggregate /*, off: Int = -1 */): Array[BigInt] = {
+ def peek(data: Aggregate /*, off: Int = -1 */): IndexedSeq[BigInt] = {
data.flatten.map(peek(_))
}
diff --git a/src/main/scala/utils.scala b/src/main/scala/utils.scala
index c6f2ec01..4135d92b 100644
--- a/src/main/scala/utils.scala
+++ b/src/main/scala/utils.scala
@@ -31,8 +31,8 @@ object isPow2
object FillInterleaved
{
- def apply(n: Int, in: Bits): Bits = apply(n, in.toBools)
- def apply(n: Int, in: Seq[Bool]): Bits = Vec(in.map(Fill(n, _))).toBits
+ def apply(n: Int, in: UInt): UInt = apply(n, in.toBools)
+ def apply(n: Int, in: Seq[Bool]): UInt = Vec(in.map(Fill(n, _))).toBits
}
/** Returns the number of bits set (i.e value is 1) in the input signal.
@@ -275,12 +275,12 @@ object Counter
}
}
-class ValidIO[+T <: Data](gen: T) extends Bundle
+class ValidIO[+T <: Data](gen2: T) extends Bundle
{
val valid = Bool(OUTPUT)
- val bits = gen.cloneType.asOutput
+ val bits = gen2.cloneType.asOutput
def fire(dummy: Int = 0): Bool = valid
- override def cloneType: this.type = new ValidIO(gen).asInstanceOf[this.type]
+ override def cloneType: this.type = new ValidIO(gen2).asInstanceOf[this.type]
}
/** Adds a valid protocol to any interface. The standard used is
@@ -415,3 +415,147 @@ object PriorityEncoderOH
}
def apply(in: Bits): UInt = encode((0 until in.getWidth).map(i => in(i)))
}
+
+class ArbiterIO[T <: Data](gen: T, n: Int) extends Bundle {
+ val in = Vec(Decoupled(gen), n).flip
+ val out = Decoupled(gen)
+ val chosen = UInt(OUTPUT, log2Up(n))
+}
+
+object ArbiterCtrl
+{
+ def apply(request: Seq[Bool]): Seq[Bool] = {
+ Bool(true) +: (1 until request.length).map(i => !request.slice(0, i).foldLeft(Bool(false))(_ || _))
+ }
+}
+
+abstract class LockingArbiterLike[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T => Bool] = None) extends Module {
+ require(isPow2(count))
+ def grant: Seq[Bool]
+ 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)))
+
+ for ((g, i) <- grant.zipWithIndex)
+ io.in(i).ready := Mux(locked, lockIdx === UInt(i), g) && io.out.ready
+ io.out.valid := io.in(chosen).valid
+ io.out.bits := io.in(chosen).bits
+ io.chosen := chosen
+
+ 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)
+ }
+ }
+ }
+}
+
+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)))
+ 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))
+ }
+
+ var choose = UInt(n-1)
+ for (i <- n-2 to 0 by -1)
+ choose = Mux(io.in(i).valid, UInt(i), choose)
+ 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 }
+}
+
+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)
+}
+
+/** Hardware module that is used to sequence n producers into 1 consumer.
+ Producers are chosen in round robin order.
+
+ Example usage:
+ val arb = new RRArbiter(2, UInt())
+ arb.io.in(0) <> producer0.io.out
+ arb.io.in(1) <> producer1.io.out
+ consumer.io.in <> arb.io.out
+ */
+class RRArbiter[T <: Data](gen:T, n: Int) extends LockingRRArbiter[T](gen, n, 1)
+
+/** Hardware module that is used to sequence n producers into 1 consumer.
+ Priority is given to lower producer
+
+ Example usage:
+ val arb = Module(new Arbiter(2, UInt()))
+ arb.io.in(0) <> producer0.io.out
+ 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)
+
+/** linear feedback shift register
+ */
+object LFSR16
+{
+ def apply(increment: Bool = Bool(true)): UInt =
+ {
+ val width = 16
+ val lfsr = Reg(init=UInt(1, width))
+ when (increment) { lfsr := Cat(lfsr(0)^lfsr(2)^lfsr(3)^lfsr(5), lfsr(width-1,1)) }
+ lfsr
+ }
+}
+
+/** A hardware module that delays data coming down the pipeline
+ by the number of cycles set by the latency parameter. Functionality
+ is similar to ShiftRegister but this exposes a Pipe interface.
+
+ Example usage:
+ val pipe = new Pipe(UInt())
+ pipe.io.enq <> produce.io.out
+ consumer.io.in <> pipe.io.deq
+ */
+object Pipe
+{
+ def apply[T <: Data](enqValid: Bool, enqBits: T, latency: Int): ValidIO[T] = {
+ if (latency == 0) {
+ val out = Valid(enqBits)
+ out.valid <> enqValid
+ out.bits <> enqBits
+ out
+ } else {
+ val v = Reg(Bool(), next=enqValid, init=Bool(false))
+ val b = RegEnable(enqBits, enqValid)
+ apply(v, b, latency-1)
+ }
+ }
+ def apply[T <: Data](enqValid: Bool, enqBits: T): ValidIO[T] = apply(enqValid, enqBits, 1)
+ def apply[T <: Data](enq: ValidIO[T], latency: Int = 1): ValidIO[T] = apply(enq.valid, enq.bits, latency)
+}
+
+class Pipe[T <: Data](gen: T, latency: Int = 1) extends Module
+{
+ val io = new Bundle {
+ val enq = Valid(gen).flip
+ val deq = Valid(gen)
+ }
+
+ io.deq <> Pipe(io.enq, latency)
+}