diff options
| author | Jim Lawson | 2015-05-11 10:04:01 -0700 |
|---|---|---|
| committer | Jim Lawson | 2015-07-24 15:50:53 -0700 |
| commit | b208bfb5691c7b5921dd47d0b599726872acd1cd (patch) | |
| tree | 5d8695f13db41a807622dfdc93c1b6841911acc8 /src/main/scala/Core.scala | |
| parent | caa7602b878c03c47fd263550e37715f1a67f854 (diff) | |
move source files under Chisel folder - eclipse compatibility
Diffstat (limited to 'src/main/scala/Core.scala')
| -rw-r--r-- | src/main/scala/Core.scala | 1248 |
1 files changed, 0 insertions, 1248 deletions
diff --git a/src/main/scala/Core.scala b/src/main/scala/Core.scala deleted file mode 100644 index 8236c154..00000000 --- a/src/main/scala/Core.scala +++ /dev/null @@ -1,1248 +0,0 @@ -package Chisel -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 { - private var counter = -1 - def nextInt: Int = { - counter += 1 - counter - } - def next(name: String): String = - name + "_" + nextInt -} - -object Builder { - val components = new ArrayBuffer[Component]() - val genSym = new GenSym() - val scopes = new Stack[HashSet[String]]() - def scope = scopes.top - val switchKeyz = new Stack[Stack[Bits]]() - def switchKeys = switchKeyz.top - def pushScope = { - scopes.push(new HashSet[String]()) - switchKeyz.push(new Stack[Bits]()) - } - def popScope = { - scopes.pop() - switchKeyz.pop() - } - val modules = new HashMap[String,Module]() - def addModule(mod: Module) { - modules(mod.cid) = mod - } - val modulez = new Stack[Module]() - def pushModule(mod: Module) { - modulez.push(mod) - } - def getComponent(): Module = if (modulez.length > 0) modulez.head else null - def popModule() { - modulez.pop - } - val componentNames = new HashSet[String]() - def UniqueComponent(name: String, ports: Array[Port], body: Command) = { - val res = Component(if (componentNames.contains(name)) genSym.next(name) else name, ports, body) - componentNames += name - res - } - val commandz = new Stack[ArrayBuffer[Command]]() - def commands = commandz.top - def pushCommand(cmd: Command) = commands += cmd - def commandify(cmds: ArrayBuffer[Command]): Command = { - if (cmds.length == 0) - EmptyCommand() - else if (cmds.length == 1) - cmds(0) - else - Begin(cmds.toList) - } - def pushCommands = - commandz.push(new ArrayBuffer[Command]()) - def popCommands: Command = { - val newCommands = commands - commandz.pop() - commandify(newCommands) - } - def collectCommands[T <: Module](f: => T): (Command, T) = { - pushCommands - val mod = f - // mod.setRefs - (popCommands, mod) - } - - private val refmap = new HashMap[String,Immediate]() - - def legalizeName (name: String) = { - if (name == "mem" || name == "node" || name == "wire" || - name == "reg" || name == "inst") - // genSym.next(name) - name + "__" - else - name - } - - def setRefForId(id: String, name: String, overwrite: Boolean = false) { - if (overwrite || !refmap.contains(id)) { - refmap(id) = Ref(legalizeName(name)) - } - } - - def setFieldForId(parentid: String, id: String, name: String) { - refmap(id) = Slot(Alias(parentid), legalizeName(name)) - } - - def setIndexForId(parentid: String, id: String, index: Int) { - refmap(id) = Index(Alias(parentid), index) - } - - def getRefForId(id: String): Immediate = { - if (refmap.contains(id)) { - refmap(id) - } else { - val ref = Ref(genSym.next("T")) - refmap(id) = ref - ref - } - } - - def build[T <: Module](f: => T): (Circuit, T) = { - val (cmd, mod) = collectCommands(f) - setRefForId(mod.cid, mod.name) - (Circuit(components.toArray, components.last.name), mod) - } - -} - -import Builder._ - -/// CHISEL IR - -case class PrimOp(val name: String) { - override def toString = name -} - -object PrimOp { - val AddOp = PrimOp("add") - val AddModOp = PrimOp("add-wrap") - val SubOp = PrimOp("sub") - val SubModOp = PrimOp("sub-wrap") - val TimesOp = PrimOp("mul") - val DivideOp = PrimOp("div") - val ModOp = PrimOp("mod") - val ShiftLeftOp = PrimOp("shl") - val ShiftRightOp = PrimOp("shr") - val DynamicShiftLeftOp = PrimOp("dshl") - val DynamicShiftRightOp = PrimOp("dshr") - val BitAndOp = PrimOp("bit-and") - val BitOrOp = PrimOp("bit-or") - val BitXorOp = PrimOp("bit-xor") - val BitNotOp = PrimOp("bit-not") - val ConcatOp = PrimOp("cat") - val BitSelectOp = PrimOp("bit") - val BitsExtractOp = PrimOp("bits") - val LessOp = PrimOp("lt") - val LessEqOp = PrimOp("leq") - val GreaterOp = PrimOp("gt") - val GreaterEqOp = PrimOp("geq") - val EqualOp = PrimOp("eq") - val PatternEqualOp = PrimOp("pattern-equal") - val PadOp = PrimOp("pad") - val NotEqualOp = PrimOp("neq") - val NegOp = PrimOp("neg") - val MultiplexOp = PrimOp("mux") - val XorReduceOp = PrimOp("xorr") - val ConvertOp = PrimOp("convert") - val AsUIntOp = PrimOp("as-UInt") - val AsSIntOp = PrimOp("as-SInt") -} -import PrimOp._ - -abstract class Immediate { - def fullname: String - def name: String - def debugName = fullname -} - -abstract class Arg extends Immediate { - def fullname: String - def name: String -} - -case class Alias(val id: String) extends Arg { - def fullname = getRefForId(id).fullname - def name = getRefForId(id).name - override def debugName = getRefForId(id).debugName - def emit: String = "Alias(" + id + ")" -} - -abstract class LitArg (val num: BigInt, val width: Int) extends Arg { -} - -case class ULit(n: BigInt, w: Int = -1) extends LitArg(n, w) { - def fullname = name - def name = "UInt<" + width + ">(" + num + ")" -} - -case class SLit(n: BigInt, w: Int = -1) extends LitArg(n, w) { - def fullname = name - def name = "SInt<" + width + ">(" + num + ")" -} - -case class Ref(val name: String) extends Immediate { - def fullname = name -} -case class Slot(val imm: Immediate, val name: String) extends Immediate { - def fullname = { - val imm_fullname = imm.fullname - if (imm_fullname == "this") name else imm_fullname + "." + name - } - override def debugName = { - val imm_debugName = imm.debugName - if (imm_debugName == "this") name else imm_debugName + "." + name - } -} -case class Index(val imm: Immediate, val value: Int) extends Immediate { - def name = "[" + value + "]" - def fullname = imm.fullname + "[" + value + "]" - override def debugName = imm.debugName + "." + value -} - -case class Port(val id: String, val dir: Direction, val kind: Kind); - -abstract class Width; -case class UnknownWidth() extends Width; -case class IntWidth(val value: Int) extends Width; - -abstract class Kind(val isFlip: Boolean); -case class UnknownType(flip: Boolean) extends Kind(flip); -case class UIntType(val width: Width, flip: Boolean) extends Kind(flip); -case class SIntType(val width: Width, flip: Boolean) extends Kind(flip); -case class FloType(flip: Boolean) extends Kind(flip); -case class DblType(flip: Boolean) extends Kind(flip); -case class BundleType(val ports: Array[Port], flip: Boolean) extends Kind(flip); -case class VectorType(val size: Int, val kind: Kind, flip: Boolean) extends Kind(flip); - -abstract class Command; -abstract class Definition extends Command { - def id: String - def name = getRefForId(id).name -} -case class DefUInt(val id: String, val value: BigInt, val width: Int) extends Definition; -case class DefSInt(val id: String, val value: BigInt, val width: Int) extends Definition; -case class DefFlo(val id: String, val value: Float) extends Definition; -case class DefDbl(val id: String, val value: Double) extends Definition; -case class DefPrim(val id: String, val kind: Kind, val op: PrimOp, val args: Array[Arg], val lits: Array[BigInt]) extends Definition; -case class DefWire(val id: String, val kind: Kind) extends Definition; -case class DefRegister(val id: String, val kind: Kind) extends Definition; -case class DefMemory(val id: String, val kind: Kind, val size: Int) extends Definition; -case class DefSeqMemory(val id: String, val kind: Kind, val size: Int) extends Definition; -case class DefAccessor(val id: String, val source: Alias, val direction: Direction, val index: Arg) extends Definition; -case class DefInstance(val id: String, val module: String) extends Definition; -case class Conditionally(val prep: Command, val pred: Arg, val conseq: Command, var alt: Command) extends Command; -case class Begin(val body: List[Command]) extends Command(); -case class Connect(val loc: Alias, val exp: Arg) extends Command; -case class BulkConnect(val loc1: Alias, val loc2: Alias) extends Command; -case class ConnectInit(val loc: Alias, val exp: Arg) extends Command; -case class ConnectInitIndex(val loc: Alias, val index: Int, val exp: Arg) extends Command; -case class EmptyCommand() extends Command; - -case class Component(val name: String, val ports: Array[Port], val body: Command); -case class Circuit(val components: Array[Component], val main: String); - -object Commands { - val NoLits = Array[BigInt]() -} - -import Commands._ - -/// COMPONENTS - -sealed abstract class Direction(val name: String) { - override def toString = name -} -object INPUT extends Direction("input") -object OUTPUT extends Direction("output") -object NO_DIR extends Direction("?") - -object Direction { - def flipDirection(dir: Direction) = { - dir match { - case INPUT => OUTPUT - case OUTPUT => INPUT - case NO_DIR => NO_DIR - } - } -} -import Direction._ - -/// CHISEL FRONT-END - -abstract class Id { - protected[Chisel] val _id = genSym.nextInt - protected[Chisel] val cid = "id_" + _id - - var isDef_ = false - def defd: this.type = { - isDef_ = true - this - } - def isDef = isDef_ -} - -object debug { - // TODO: - def apply (arg: Data) = arg -} - -abstract class Data(dirArg: Direction) extends Id { - val mod = getComponent() - def toType: Kind - var isFlipVar = dirArg == INPUT - def isFlip = isFlipVar - def dir: Direction = if (isFlip) INPUT else OUTPUT - def setDir(dir: Direction) { - isFlipVar = (dir == INPUT) - } - def init(dummy:Int = 0) = { } - def asInput: this.type = { - setDir(INPUT) - this - } - def asOutput: this.type = { - setDir(OUTPUT) - this - } - def flip(): this.type = { - isFlipVar = !isFlipVar - this - } - def :=(other: Data) = - pushCommand(Connect(this.lref, other.ref)) - def <>(other: Data) = - pushCommand(BulkConnect(this.lref, other.lref)) - final def cloneType: this.type = { - val res = doCloneType - collectElts - res - } - def collectElts = { } - def doCloneType: this.type - def cloneTypeWidth(width: Int): this.type - def lref: Alias = - Alias(cid) - def ref: Arg = - if (isLitValue) litArg() else Alias(cid) - def name = getRefForId(cid).name - def debugName = mod.debugName + "." + getRefForId(cid).debugName - def litArg(): LitArg = null - def litValue(): BigInt = -1 - def isLitValue(): Boolean = false - def setLitValue(x: LitArg) { } - def floLitValue: Float = intBitsToFloat(litValue().toInt) - def dblLitValue: Double = longBitsToDouble(litValue().toLong) - 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: IndexedSeq[Bits] - def fromBits(n: Bits): this.type = { - var i = 0 - val wire = Wire(this.cloneType) - for (x <- wire.flatten.reverse) { - x := n(i + x.getWidth-1, i) - i += x.getWidth - } - wire.asInstanceOf[this.type] - } - def toBits: UInt = { - val elts = this.flatten.reverse - Cat(elts.head, elts.tail:_*).asUInt - } - def makeLit(value: BigInt, width: Int): this.type = - this.fromBits(Bits(value, width)) - - def toPort: Port = Port(cid, dir, toType) - var isReg_ = false - def isReg = isReg_ - def params = if(Driver.parStack.isEmpty) Parameters.empty else Driver.parStack.top -} - -object Wire { - def apply[T <: Data](t: T = null, init: T = null): T = { - val mType = if (t == null) init else t - if(mType == null) - throw new Exception("cannot infer type of Init.") - val x = mType.cloneType - // TODO: COME UP WITH MORE ROBUST WAY TO HANDLE THIS - pushCommand(DefWire(x.defd.cid, x.toType)) - if (init != null) - pushCommand(Connect(x.lref, init.ref)) - x - } -} - -object Reg { - def apply[T <: Data](t: T = null, next: T = null, init: T = null): T = { - var mType = t - if(mType == null) - mType = next - if(mType == null) - mType = init - if(mType == null) - throw new Exception("cannot infer type of Reg.") - val x = mType.cloneType - x.isReg_ = true - pushCommand(DefRegister(x.defd.cid, x.toType)) - if (init != null) - pushCommand(ConnectInit(x.lref, init.ref)) - if (next != null) - x := next - x - } - def apply[T <: Data](outType: T): T = Reg[T](outType, null.asInstanceOf[T], null.asInstanceOf[T]) -} - -object Mem { - def apply[T <: Data](t: T, size: Int): Mem[T] = { - val mt = t.cloneType - val mem = new Mem(mt, size) - pushCommand(DefMemory(mt.defd.cid, mt.toType, size)) - mem - } -} - -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)) - x - } - - 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] = - new SeqMem(t, size) -} - -// For now, implement SeqMem in terms of Mem -class SeqMem[T <: Data](t: T, n: Int) { - private val mem = Mem(t, n) - - def read(addr: UInt): T = mem.read(Reg(next = addr)) - def read(addr: UInt, enable: Bool): T = mem.read(RegEnable(addr, enable)) - - 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 { - def apply[T <: Data](gen: => T, n: Int): Vec[T] = - 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)) - val isDef = true || elts.head.isDef - if (vec.isReg) - throw new Exception("Vec of Reg Deprecated.") - if (isDef) { - pushCommand(DefWire(vec.defd.cid, vec.toType)) - var i = 0 - for (elt <- elts) { - vec(i) := elt - i += 1 - } - } - vec - } - def apply[T <: Data](elt0: T, elts: T*): Vec[T] = - apply(elt0 +: elts.toSeq) - def tabulate[T <: Data](n: Int)(gen: (Int) => T): Vec[T] = - apply((0 until n).map(i => gen(i))) - def fill[T <: Data](n: Int)(gen: => T): Vec[T] = - Vec.tabulate(n){ i => gen } -} - -abstract class Aggregate(dirArg: Direction) extends Data(dirArg) { - def cloneTypeWidth(width: Int): this.type = cloneType -} - -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 " + this) - for ((e, i) <- self zipWithIndex) { - // println(" NAME " + i + " -> " + cid) - e.collectElts - setIndexForId(cid, e.cid, i) - } - // println("DONE VEC NAMING " + this) - - def <> (that: Iterable[T]): Unit = - this <> Vec(that).asInstanceOf[Data] - - override def isReg = elt0.isReg - override def isFlip = { - val isSubFlip = elt0.isFlip - if (isFlipVar) !isSubFlip else isSubFlip - } - - def apply(idx: UInt): T = { - val x = elt0.cloneType - pushCommand(DefAccessor(x.defd.cid, Alias(cid), NO_DIR, idx.ref)) - x - } - def apply(idx: Int): T = - self(idx) - def toPorts: Array[Port] = - self.map(d => d.toPort).toArray - def toType: Kind = - VectorType(self.size, elt0.toType, isFlipVar) - override def doCloneType: 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) = - pushCommand(ConnectInitIndex(elt.lref, index, init.ref)) - for (d <- self) { - f(i, d, doInit) - i += 1; - } - } - override def flatten: IndexedSeq[Bits] = - self.map(_.flatten).reduce(_ ++ _) - - def length: Int = self.size - - def read(idx: UInt): T = apply(idx) - def write(idx: UInt, data: T): Unit = apply(idx) := data -} - -trait VecLike[T <: Data] extends collection.IndexedSeq[T] { - def read(idx: UInt): T - def write(idx: UInt, data: T): Unit - def apply(idx: UInt): T - - def forall(p: T => Bool): Bool = (this map p).fold(Bool(true))(_&&_) - def exists(p: T => Bool): Bool = (this map p).fold(Bool(false))(_||_) - def contains(x: T) (implicit evidence: T <:< Bits): Bool = this.exists(_ === x) - def count(p: T => Bool): UInt = PopCount((this map p).toSeq) - - private def indexWhereHelper(p: T => Bool) = this map p zip (0 until length).map(i => UInt(i)) - def indexWhere(p: T => Bool): UInt = PriorityMux(indexWhereHelper(p)) - def lastIndexWhere(p: T => Bool): UInt = PriorityMux(indexWhereHelper(p).reverse) - def onlyIndexWhere(p: T => Bool): UInt = Mux1H(indexWhereHelper(p)) -} - -// object chiselCast { -// def apply[S <: Data, T <: Bits](i: S)(gen: Int => T): T = { -// val b = i.toBits -// val x = gen(b.getWidth) -// pushCommand(DefPrim(x.defd.id, x.toType, ConvertOp, Array(b.ref), NoLits)) -// x -// } -// } - -import Literal._ - -class BitPat(val value: String, val width: Int) extends Data(NO_DIR) { - def cloneTypeWidth(width: Int): this.type = cloneType - 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: IndexedSeq[Bits] = throw new Exception("BitPat.flatten") - override def doCloneType: this.type = - new BitPat(value, width).asInstanceOf[this.type] - def fromInt(x: BigInt): BitPat = BitPat(x.toString(2), -1).asInstanceOf[this.type] - val (bits, mask, swidth) = parseLit(value) - def zEquals(other: Bits): Bool = - (Bits(toLitVal(mask, 2)) & other) === Bits(toLitVal(bits, 2)) - def === (other: Bits): Bool = zEquals(other) - def != (other: Bits): Bool = !zEquals(other) -} - -object BitPat { - def mintLit(n: String, width: Int) = { - assert(n(0) == 'b', "BINARY MINTS ONLY") - new BitPat(n.substring(1, n.length), width) - } - def apply(value: String, width: Int): BitPat = mintLit(value, width) - def apply(value: String): BitPat = apply(value, -1) -} - -abstract class Element(dirArg: Direction, val width: Int) extends Data(dirArg) { - override def getWidth: Int = width -} - -abstract class Bits(dirArg: Direction, width: Int) extends Element(dirArg, width) { - private var litValueVar: Option[LitArg] = None - - override def litArg(): LitArg = litValueVar.get - override def isLitValue(): Boolean = litValueVar.isDefined - override def litValue(): BigInt = if (isLitValue) litValueVar.get.num else -1 - override def setLitValue(x: LitArg) { litValueVar = Some(x) } - override def doCloneType : this.type = cloneTypeWidth(width) - def fromInt(x: BigInt): this.type = makeLit(x, -1) - - override def flatten: IndexedSeq[Bits] = IndexedSeq(this) - - final def apply(x: BigInt): Bool = { - val d = new Bool(dir) - if (isLitValue()) - d.setLitValue(ULit((litValue() >> x.toInt) & 1, 1)) - else - pushCommand(DefPrim(d.defd.cid, d.toType, BitSelectOp, Array(this.ref), Array(x))) - d - } - final def apply(x: Int): Bool = - apply(BigInt(x)) - final def apply(x: UInt): Bool = - apply(x.litValue()) - - final def apply(x: BigInt, y: BigInt): UInt = { - val w = (x - y + 1).toInt - val d = UInt(width = w) - if (isLitValue()) { - val mask = (BigInt(1)<<d.getWidth)-BigInt(1) - d.setLitValue(ULit((litValue() >> y.toInt) & mask, w)) - } else - pushCommand(DefPrim(d.defd.cid, d.toType, BitsExtractOp, Array(this.ref), Array(x, y))) - d - } - final def apply(x: Int, y: Int): UInt = - apply(BigInt(x), BigInt(y)) - final def apply(x: UInt, y: UInt): UInt = - apply(x.litValue(), y.litValue()) - - def maxWidth(other: Bits, amt: Int): Int = - if (getWidth >= 0 && other.getWidth >= 0) ((getWidth max other.getWidth) + amt) else -1 - override def sumWidth(amt: BigInt): Int = if (getWidth >= 0) (getWidth + amt).toInt else -1 - def sumWidth(other: Bits, amt: BigInt): Int = - if (getWidth >= 0 && other.getWidth >= 0) (getWidth + other.getWidth + amt).toInt else -1 - def sumLog2Width(other: Bits): Int = - if (getWidth >= 0 && other.getWidth >= 0) (getWidth + (1<<other.getWidth)).toInt else -1 - - def :=(other: Bits) = - pushCommand(Connect(this.lref, other.ref)) - - 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)) - d - } - protected[Chisel] def binop(op: PrimOp, other: BigInt, width: Int): this.type = { - val d = cloneTypeWidth(width) - pushCommand(DefPrim(d.defd.cid, d.toType, op, Array(this.ref), Array(other))) - d - } - protected[Chisel] def binop(op: PrimOp, other: Bits, width: Int): this.type = { - val d = cloneTypeWidth(width) - pushCommand(DefPrim(d.defd.cid, d.toType, op, Array(this.ref, other.ref), NoLits)) - d - } - protected[Chisel] def compop(op: PrimOp, other: Bits): Bool = { - val d = new Bool(dir) - pushCommand(DefPrim(d.defd.cid, d.toType, op, Array(this.ref, other.ref), NoLits)) - d - } - - def unary_- : Bits = Bits(0) - this - def unary_-% : Bits = Bits(0) -% this - def +& (other: Bits): Bits = binop(AddOp, other, maxWidth(other, 1)) - def + (other: Bits): Bits = this +% other - def +% (other: Bits): Bits = binop(AddModOp, other, maxWidth(other, 0)) - def -& (other: Bits): Bits = binop(SubOp, other, maxWidth(other, 1)) - def -% (other: Bits): Bits = binop(SubModOp, other, maxWidth(other, 0)) - def - (other: Bits): Bits = this -% other - def * (other: Bits): Bits = binop(TimesOp, other, sumWidth(other, 0)) - def / (other: Bits): Bits = binop(DivideOp, other, sumWidth(0)) - def % (other: Bits): Bits = binop(ModOp, other, sumWidth(0)) - def << (other: BigInt): Bits = binop(ShiftLeftOp, other, sumWidth(other)) - def << (other: Int): Bits = this << BigInt(other) - def << (other: Bits): Bits = binop(DynamicShiftLeftOp, other, sumLog2Width(other)) - def >> (other: BigInt): Bits = binop(ShiftRightOp, other, sumWidth(-other)) - def >> (other: Int): Bits = this >> BigInt(other) - def >> (other: Bits): Bits = binop(DynamicShiftRightOp, other, sumWidth(0)) - def unary_~ : Bits = unop(BitNotOp, sumWidth(0)) - def pad (other: BigInt): Bits = binop(PadOp, other, other.toInt) - - def & (other: Bits): Bits = binop(BitAndOp, other, maxWidth(other, 0)) - def | (other: Bits): Bits = binop(BitOrOp, other, maxWidth(other, 0)) - def ^ (other: Bits): Bits = binop(BitXorOp, other, maxWidth(other, 0)) - def ## (other: Bits): Bits = Cat(this, other) - - def < (other: Bits): Bool = compop(LessOp, other) - def > (other: Bits): Bool = compop(GreaterOp, other) - def === (other: Bits): Bool = compop(EqualOp, other) - def != (other: Bits): Bool = compop(NotEqualOp, other) - def <= (other: Bits): Bool = compop(LessEqOp, other) - def >= (other: Bits): Bool = compop(GreaterEqOp, other) - def unary_! : Bool = this === Bits(0) - - private def bits_redop(op: PrimOp): Bool = { - val d = new Bool(dir) - pushCommand(DefPrim(d.defd.cid, d.toType, op, Array(this.ref), NoLits)) - d - } - - def orR = !(this === Bits(0)) - def andR = (this === Bits(-1)) - def xorR = bits_redop(XorReduceOp) - - def bitSet(off: UInt, dat: Bits): Bits = { - val bit = UInt(1, 1) << off - this & ~bit | dat.toSInt & bit - } - - def toBools: Vec[Bool] = Vec.tabulate(this.getWidth)(i => this(i)) - - def asSInt(): SInt - def asUInt(): UInt - def toSInt(): SInt - def toUInt(): UInt - def toBool(): Bool = this(0) -} - -abstract trait Num[T <: Data] { - // def << (b: T): T; - // def >> (b: T): T; - //def unary_-(): T; - def + (b: T): T; - def * (b: T): T; - def / (b: T): T; - def % (b: T): T; - def - (b: T): T; - def < (b: T): Bool; - def <= (b: T): Bool; - def > (b: T): Bool; - def >= (b: T): Bool; - - def min(b: T): T = Mux(this < b, this.asInstanceOf[T], b) - def max(b: T): T = Mux(this < b, b, this.asInstanceOf[T]) -} - -class UInt(dir: Direction, width: Int) extends Bits(dir, width) with Num[UInt] { - override def cloneTypeWidth(w: Int): this.type = - new UInt(dir, w).asInstanceOf[this.type] - - def toType: Kind = - UIntType(if (width == -1) UnknownWidth() else IntWidth(width), isFlipVar) - - override def makeLit(value: BigInt, width: Int): this.type = - UInt(value, width).asInstanceOf[this.type] - - override def unary_- = UInt(0) - this - override def unary_-% = UInt(0) -% this - def +& (other: UInt): UInt = binop(AddOp, other, maxWidth(other, 1)) - def + (other: UInt): UInt = this +% other - def +% (other: UInt): UInt = binop(AddModOp, other, maxWidth(other, 0)) - def -& (other: UInt): UInt = binop(SubOp, other, maxWidth(other, 1)) - def - (other: UInt): UInt = this -% other - def -% (other: UInt): UInt = binop(SubModOp, other, maxWidth(other, 0)) - def * (other: UInt): UInt = binop(TimesOp, other, sumWidth(other, 0)) - def / (other: UInt): UInt = binop(DivideOp, other, sumWidth(0)) - def % (other: UInt): UInt = binop(ModOp, other, sumWidth(0)) - override def << (other: BigInt): UInt = binop(ShiftLeftOp, other, sumWidth(other)) - override def << (other: Int): UInt = this << BigInt(other) - def << (other: UInt): UInt = binop(DynamicShiftLeftOp, other, sumLog2Width(other)) - override def >> (other: BigInt): UInt = binop(ShiftRightOp, other, sumWidth(-other)) - override def >> (other: Int): UInt = this >> BigInt(other) - def >> (other: UInt): UInt = binop(DynamicShiftRightOp, other, sumWidth(0)) - - override def unary_~ : UInt = unop(BitNotOp, sumWidth(0)) - def & (other: UInt): UInt = binop(BitAndOp, other, maxWidth(other, 0)) - def | (other: UInt): UInt = binop(BitOrOp, other, maxWidth(other, 0)) - def ^ (other: UInt): UInt = binop(BitXorOp, other, maxWidth(other, 0)) - def ## (other: UInt): UInt = Cat(this, other) - - def < (other: UInt): Bool = compop(LessOp, other) - def > (other: UInt): Bool = compop(GreaterOp, other) - def === (other: UInt): Bool = compop(EqualOp, other) - def != (other: UInt): Bool = compop(NotEqualOp, other) - def <= (other: UInt): Bool = compop(LessEqOp, other) - def >= (other: UInt): Bool = compop(GreaterEqOp, other) - - override def pad (other: BigInt): UInt = binop(PadOp, other, other.toInt) - - def zext(): SInt = { - val x = SInt(width = getWidth + 1) - pushCommand(DefPrim(x.defd.cid, x.toType, ConvertOp, Array(ref), NoLits)) - x - } - - def asSInt(): SInt = { - val x = SInt(width = getWidth) - pushCommand(DefPrim(x.defd.cid, x.toType, AsSIntOp, Array(ref), NoLits)) - x - } - - def toSInt(): SInt = asSInt() - def toUInt(): UInt = this - def asUInt(): UInt = this -} - -trait UIntFactory { - def apply(dir: Direction = OUTPUT, width: Int = -1) = - new UInt(dir, width) - def uintLit(value: BigInt, width: Int) = { - val w = if (width == -1) (1 max bitLength(value)) else width - // println("UINT-LIT VALUE = " + value + "(b" + value.toString(2) + ") WIDTH " + w) - val b = new UInt(NO_DIR, w) - b.setLitValue(ULit(value, w)) - // pushCommand(DefUInt(b.defd.id, value, w)) - b - } - def apply(value: BigInt, width: Int): UInt = uintLit(value, width) - def apply(value: BigInt): UInt = apply(value, -1) - def apply(n: String, width: Int): UInt = { - val bitsPerDigit = if (n(0) == 'b') 1 else if (n(0) == 'h') 4 else -1 - apply(stringToVal(n(0), n.substring(1, n.length)), - if (width == -1) (bitsPerDigit * (n.length-1)) else width) - } - def apply(n: String): UInt = apply(n, -1) -} - -// Bits constructors are identical to UInt constructors. -object Bits extends UIntFactory -object UInt extends UIntFactory - -class SInt(dir: Direction, width: Int) extends Bits(dir, width) with Num[SInt] { - override def cloneTypeWidth(w: Int): this.type = - new SInt(dir, w).asInstanceOf[this.type] - def toType: Kind = - SIntType(if (width == -1) UnknownWidth() else IntWidth(width), isFlipVar) - - override def makeLit(value: BigInt, width: Int): this.type = - SInt(value, width).asInstanceOf[this.type] - - override def unary_- : SInt = SInt(0, getWidth) - this - override def unary_-% : SInt = SInt(0, getWidth) -% this - def +& (other: SInt): SInt = binop(AddOp, other, maxWidth(other, 1)) - def +% (other: SInt): SInt = binop(AddModOp, other, maxWidth(other, 0)) - def + (other: SInt): SInt = this +% other - def -& (other: SInt): SInt = binop(SubOp, other, maxWidth(other, 1)) - def -% (other: SInt): SInt = binop(SubModOp, other, maxWidth(other, 0)) - def - (other: SInt): SInt = this -% other - def * (other: SInt): SInt = binop(TimesOp, other, sumWidth(other, 0)) - def / (other: SInt): SInt = binop(DivideOp, other, sumWidth(0)) - def % (other: SInt): SInt = binop(ModOp, other, sumWidth(0)) - override def << (other: BigInt): SInt = binop(ShiftLeftOp, other, sumWidth(other)) - override def << (other: Int): SInt = this << BigInt(other) - def << (other: UInt): SInt = binop(DynamicShiftLeftOp, other, sumLog2Width(other)) - override def >> (other: BigInt): SInt = binop(ShiftRightOp, other, sumWidth(-other)) - override def >> (other: Int): SInt = this >> BigInt(other) - def >> (other: UInt): SInt = binop(DynamicShiftRightOp, other, sumWidth(0)) - - override def unary_~ : SInt = unop(BitNotOp, sumWidth(0)) - def & (other: SInt): SInt = binop(BitAndOp, other, maxWidth(other, 0)) - def | (other: SInt): SInt = binop(BitOrOp, other, maxWidth(other, 0)) - def ^ (other: SInt): SInt = binop(BitXorOp, other, maxWidth(other, 0)) - - def < (other: SInt): Bool = compop(LessOp, other) - def > (other: SInt): Bool = compop(GreaterOp, other) - def === (other: SInt): Bool = compop(EqualOp, other) - 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) - - def asUInt(): UInt = { - val x = UInt(width = getWidth) - pushCommand(DefPrim(x.defd.cid, x.toType, AsUIntOp, Array(ref), NoLits)) - x - } - def toUInt(): UInt = asUInt() - def asSInt(): SInt = this - def toSInt(): SInt = this -} - -object SInt { - def apply(dir: Direction = OUTPUT, width: Int = -1) = - new SInt(dir, width) - def sintLit(value: BigInt, width: Int) = { - val w = if (width == -1) bitLength(value) + 1 else width - val b = new SInt(NO_DIR, w) - b.setLitValue(SLit(value, w)) - // pushCommand(DefSInt(b.defd.id, value, w)) - b - } - def apply(value: BigInt, width: Int): SInt = sintLit(value, width) - def apply(value: BigInt): SInt = apply(value, -1) - def apply(n: String, width: Int): SInt = - apply(stringToVal(n(0), n.substring(1, n.length)), width) - def apply(n: String): SInt = apply(n, -1) -} - -class Bool(dir: Direction) extends UInt(dir, 1) { - override def cloneTypeWidth(w: Int): this.type = new Bool(dir).asInstanceOf[this.type] - - override def makeLit(value: BigInt, width: Int): this.type = - Bool(value).asInstanceOf[this.type] - - def & (other: Bool): Bool = super.&(other).asInstanceOf[Bool] - def | (other: Bool): Bool = super.|(other).asInstanceOf[Bool] - def ^ (other: Bool): Bool = super.^(other).asInstanceOf[Bool] - override def unary_~ : Bool = super.unary_~.asInstanceOf[Bool] - - def || (that: Bool): Bool = this | that - def && (that: Bool): Bool = this & that -} -object Bool { - def apply(dir: Direction) : Bool = - new Bool(dir) - def apply() : Bool = - apply(NO_DIR) - def boolLit(value: BigInt) = { - val b = new Bool(NO_DIR) - b.setLitValue(ULit(value, 1)) - b - } - def apply(value: BigInt) : Bool = boolLit(value) - def apply(value: Boolean) : Bool = apply(if (value) 1 else 0) -} - -object Mux { - def apply[T <: Data](cond: Bool, con: T, alt: T): T = { - val w = Wire(alt, init = alt) - when (cond) { - w := con - } - w - } -} - -object Cat { - def apply[T <: Bits](a: T, r: T*): T = apply(a :: r.toList) - def apply[T <: Bits](r: Seq[T]): T = doCat(r) - private def doCat[T <: Data](r: Seq[T]): T = { - if (r.tail.isEmpty) - r.head - else { - val l = doCat(r.slice(0, r.length/2)) - val h = doCat(r.slice(r.length/2, r.length)) - val isConst = (l.isLitValue() && h.isLitValue()) - val w = if (isConst) l.getWidth + h.getWidth else if (l.getWidth >= 0 && h.getWidth >= 0) l.getWidth + h.getWidth else -1 - val d = l.cloneTypeWidth(w) - if (isConst) { - val c = (l.litValue() << h.getWidth) | h.litValue() - // println("DO-CAT L = " + l.litValue() + " LW = " + l.getWidth + " H = " + h.litValue() + " -> " + c) - - d.setLitValue(ULit(c, w)) - } else - pushCommand(DefPrim(d.cid, d.toType, ConcatOp, Array(l.ref, h.ref), NoLits)) - d - } - } -} - -object Bundle { - val keywords = HashSet[String]("elements", "flip", "toString", - "flatten", "binding", "asInput", "asOutput", "unary_$tilde", - "unary_$bang", "unary_$minus", "cloneType", "doCloneType", - "toUInt", "toBits", - "toBool", "toSInt", "asDirectionless") - def apply[T <: Bundle](b: => T)(implicit p: Parameters): T = { - Driver.parStack.push(p.push) - val res = b - Driver.parStack.pop - res - } - def apply[T <: Bundle](b: => T, f: PartialFunction[Any,Any]): T = { - val q = params.alterPartial(f) - apply(b)(q) - } - private def params = if(Driver.parStack.isEmpty) Parameters.empty else Driver.parStack.top -} - -class Bundle(dirArg: Direction = NO_DIR) extends Aggregate(dirArg) { - def toPorts: Array[Port] = - elements.map(_._2.toPort).toArray - def toType: BundleType = - BundleType(this.toPorts, isFlipVar) - - override def flatten: IndexedSeq[Bits] = { - val sortedElts = elements.values.toIndexedSeq sortWith (_._id < _._id) - sortedElts.map(_.flatten).reduce(_ ++ _) - } - - 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 - // 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) - elts(name) = data - case _ => () - } - } - } - // println("DONE BUNDLE NAMING " + cid) - elts - } - override def collectElts = elements - - override def doCloneType : this.type = { - try { - val constructor = this.getClass.getConstructors.head - val res = constructor.newInstance(Array.fill(constructor.getParameterTypes.size)(null):_*) - 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) - val s = "CLONE INVOCATION EXCEPTION " + this.getClass - error(s) - case e: java.lang.Exception => - val s = "CLONE ANY EXCEPTION " + this.getClass - error(s) - // throwException("Parameterized Bundle " + this.getClass + " needs cloneType method", e) - } - } -} - -object Module { - def apply[T <: Module](bc: => T)(implicit p: Parameters = params): T = { - Driver.modStackPushed = true - Driver.parStack.push(p.push) - val m = bc - val cmd = popCommands - popScope - popModule - m.setRefs - val ports = m.io.toPorts - val component = UniqueComponent(m.name, ports, cmd) - components += component - pushCommand(DefInstance(m.defd.cid, component.name)) - Driver.parStack.pop - m - } - def apply[T <: Module](m: => T, f: PartialFunction[Any,Any]): T = { - val q = params.alterPartial(f) - apply(m)(q) - } - private def params = if(Driver.parStack.isEmpty) Parameters.empty else Driver.parStack.top -} - -abstract class Module(private[Chisel] _reset: Bool = null) extends Id { - val parent = modulez.headOption - pushModule(this) - pushScope - pushCommands - addModule(this) - - lazy val params = Module.params - params.path = this.getClass :: params.path - - def io: Bundle - def ref = getRefForId(cid) - def lref = ref - val reset = if (_reset == null) Bool().defd else _reset - setRefForId(reset.cid, "reset") - - def name = { - // getClass.getName.replace('.', '_') - getClass.getName.split('.').last - } - def debugName: String = { - val p = parent.getOrElse(null) - val pname = if (p == null) "" else (p.debugName + ".") - pname + getRefForId(cid).debugName - } - - def setRefs { - setRefForId(io.cid, "this") - - for (m <- getClass.getDeclaredMethods) { - val name = m.getName() - val types = m.getParameterTypes() - if (types.length == 0) { - val obj = m.invoke(this) - obj match { - case module: Module => - setRefForId(module.cid, name) - module.setRefs - case bundle: Bundle => - if (name != "io") { - setRefForId(bundle.cid, name) - } - case mem: Mem[_] => - setRefForId(mem.t.cid, name) - case vec: Vec[_] => - setRefForId(vec.cid, name) - case data: Data => - setRefForId(data.cid, name) - // ignore anything not of those types - case _ => null - } - } - } - } - - // TODO: actually implement assert - def assert(cond: Bool, msg: String): Unit = {} -} - -// TODO: actually implement BlackBox (this hack just allows them to compile) -abstract class BlackBox(private[Chisel] _reset: Bool = null) extends Module(_reset) { - def setVerilogParameters(s: String): Unit = {} -} - -object when { - def execBlock(block: => Unit): Command = { - pushScope - pushCommands - block - val cmd = popCommands - popScope - cmd - } - def apply(cond: => Bool)(block: => Unit): when = { - new when(cond)( block ) - } -} - -import when._ - -class when(cond: => Bool)(block: => Unit) { - def elsewhen (cond: => Bool)(block: => Unit): when = { - pushCommands - val res = new when(cond) ( block ) - this.cmd.alt = popCommands - res - } - - def otherwise (block: => Unit) { - this.cmd.alt = execBlock(block) - } - - // Capture any commands we need to set up the conditional test. - pushCommands - val pred = cond.ref - val prep = popCommands - val conseq = execBlock(block) - // Assume we have an empty alternate clause. - // elsewhen and otherwise will update it if that isn't the case. - val cmd = Conditionally(prep, pred, conseq, EmptyCommand()) - pushCommand(cmd) -} - - -/// CHISEL IR EMITTER - -class Emitter { - var indenting = 0 - def withIndent(f: => String) = { - indenting += 1; - val res = f - indenting -= 1; - res - } - def join(parts: Array[String], sep: String) = - parts.foldLeft("")((s, p) => if (s == "") p else s + sep + p) - def join0(parts: Array[String], sep: String) = - parts.foldLeft("")((s, p) => s + sep + p) - def join0(parts: List[String], sep: String) = - parts.foldLeft("")((s, p) => s + sep + p) - def newline = - "\n" + join((0 until indenting).map(x => " ").toArray, "") - def emitDir(e: Direction, isTop: Boolean): String = - if (isTop) (e.name + " ") else if (e == INPUT) "flip " else "" - def emit(e: PrimOp): String = e.name - def emit(e: Arg): String = e.fullname - def emitPort(e: Port, isTop: Boolean): String = - emitDir(e.dir, isTop) + getRefForId(e.id).name + " : " + emitType(e.kind) - def emit(e: Width): String = { - e match { - case e: UnknownWidth => "" - case e: IntWidth => "<" + e.value.toString + ">" - } - } - def emitType(e: Kind): String = { - e match { - case e: UnknownType => "?" - case e: UIntType => "UInt" + emit(e.width) - case e: SIntType => "SInt" + emit(e.width) - case e: BundleType => "{" + join(e.ports.map(x => emitPort(x, false)), ", ") + "}" - case e: VectorType => emitType(e.kind) + "[" + e.size + "]" - } - } - def emit(e: Command): String = { - def maybeWidth (w: Int) = if (w == -1) "<?>" else ("<" + w + ">") - e match { - case e: DefUInt => "node " + e.name + " = UInt" + maybeWidth(e.width) + "(" + e.value + ")" - case e: DefSInt => "node " + e.name + " = SInt" + maybeWidth(e.width) + "(" + e.value + ")" - case e: DefFlo => "node " + e.name + " = Flo(" + e.value + ")" - case e: DefDbl => "node " + e.name + " = Dbl(" + e.value + ")" - case e: DefPrim => - "node " + e.name + " = " + emit(e.op) + "(" + join(e.args.map(x => emit(x)) ++ e.lits.map(x => x.toString), ", ") + ")" - case e: DefWire => "wire " + e.name + " : " + emitType(e.kind) - case e: DefRegister => "reg " + e.name + " : " + emitType(e.kind) - case e: DefMemory => "cmem " + e.name + " : " + emitType(e.kind) + "[" + e.size + "]"; - case e: DefSeqMemory => "smem " + e.name + " : " + emitType(e.kind) + "[" + e.size + "]"; - case e: DefAccessor => "accessor " + e.name + " = " + emit(e.source) + "[" + emit(e.index) + "]" - case e: DefInstance => { - val mod = modules(e.id) - // update all references to the modules ports - setRefForId(mod.io.cid, e.name, true) - "inst " + e.name + " of " + e.module - } - case e: Conditionally => { - val prefix = if (!e.prep.isInstanceOf[EmptyCommand]) { - newline + emit(e.prep) + newline - } else { - "" - } - val suffix = if (!e.alt.isInstanceOf[EmptyCommand]) { - newline + "else : " + withIndent{ newline + emit(e.alt) } - } else { - "" - } - prefix + "when " + emit(e.pred) + " : " + withIndent{ emit(e.conseq) } + suffix - } - case e: Begin => join0(e.body.map(x => emit(x)), newline) - case e: Connect => emit(e.loc) + " := " + emit(e.exp) - case e: BulkConnect => emit(e.loc1) + " <> " + emit(e.loc2) - case e: ConnectInit => "on-reset " + emit(e.loc) + " := " + emit(e.exp) - case e: ConnectInitIndex => "on-reset " + emit(e.loc) + "[" + e.index + "] := " + emit(e.exp) - case e: EmptyCommand => "skip" - } - } - def emit(e: Component): String = { - withIndent{ "module " + e.name + " : " + - join0(e.ports.map(x => emitPort(x, true)), newline) + - newline + emit(e.body) } - } - def emit(e: Circuit): String = - withIndent{ "circuit " + e.main + " : " + join0(e.components.map(x => emit(x)), newline) } -} |
