summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjackbackrack2015-07-24 07:40:43 -0700
committerjackbackrack2015-07-24 07:40:43 -0700
commitea31aa07364fd41e54d6426395a7cc390a525703 (patch)
tree5ac2fec5f71159b68462b56065a92cf913b8a3aa
parent10bf9045159ee0cb996a39b1dc0453ab82efdfb9 (diff)
parent40679ea4ba680427959d981547c33c7f00602337 (diff)
use delayed init to ensure collectelts and further improve walk bundle and changed getDeclaredMethods to getMethods for inheritance but still gets constructor param
-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)
+}