diff options
| author | Henry Cook | 2015-08-13 01:14:55 -0700 |
|---|---|---|
| committer | Henry Cook | 2015-08-13 01:14:55 -0700 |
| commit | 976ff1439f51afc08c61ff39ecf0ad2e71a88e2a (patch) | |
| tree | ce77dd94dd84fc024efc372fa444b712aea8c974 /src/main | |
| parent | 85d7403f9bf7bc2b3520f924736c237f21f70ebd (diff) | |
Streamline files, breaking up Core.scala and resorting some smaller ones
Diffstat (limited to 'src/main')
| -rw-r--r-- | src/main/scala/Chisel/Builder.scala | 83 | ||||
| -rw-r--r-- | src/main/scala/Chisel/Core.scala | 351 | ||||
| -rw-r--r-- | src/main/scala/Chisel/Emitter.scala | 80 | ||||
| -rw-r--r-- | src/main/scala/Chisel/Enum.scala | 43 | ||||
| -rw-r--r-- | src/main/scala/Chisel/IR.scala | 175 | ||||
| -rw-r--r-- | src/main/scala/Chisel/Literal.scala | 16 | ||||
| -rw-r--r-- | src/main/scala/Chisel/Log2.scala | 35 | ||||
| -rw-r--r-- | src/main/scala/Chisel/Utils.scala | 41 |
8 files changed, 390 insertions, 434 deletions
diff --git a/src/main/scala/Chisel/Builder.scala b/src/main/scala/Chisel/Builder.scala new file mode 100644 index 00000000..511fea78 --- /dev/null +++ b/src/main/scala/Chisel/Builder.scala @@ -0,0 +1,83 @@ +package Chisel +import scala.util.DynamicVariable +import scala.collection.mutable.{ArrayBuffer, HashMap} + +private class IdGen { + private var counter = -1L + def next: Long = { + counter += 1 + counter + } +} + +class RefMap { + private val _refmap = new HashMap[Long,Immediate]() + + def setRef(id: Id, ref: Immediate): Unit = + _refmap(id._id) = ref + + def setRefForId(id: Id, name: String)(implicit namespace: Namespace = Builder.globalNamespace): Unit = + if (!_refmap.contains(id._id)) + setRef(id, Ref(namespace.name(name))) + + def setFieldForId(parentid: Id, id: Id, name: String): Unit = { + _refmap(id._id) = Slot(Alias(parentid), name) + } + + def setIndexForId(parentid: Id, id: Id, index: Int): Unit = + _refmap(id._id) = Index(Alias(parentid), index) + + def apply(id: Id): Immediate = _refmap(id._id) +} + +private class DynamicContext { + val idGen = new IdGen + val globalNamespace = new FIRRTLNamespace + val globalRefMap = new RefMap + val components = ArrayBuffer[Component]() + val currentModuleVar = new DynamicVariable[Option[Module]](None) + val currentParamsVar = new DynamicVariable[Parameters](Parameters.empty) + val parameterDump = new ParameterDump + + def getCurrentModule = currentModuleVar.value + def moduleScope[T](body: => T): T = { + currentModuleVar.withValue(getCurrentModule)(body) + } + def forceCurrentModule[T](m: Module) { // Used in Module constructor + currentModuleVar.value = Some(m) + } + def pushCommand(c: Command) { + currentModuleVar.value.foreach(_._commands += c) + } + + def getParams: Parameters = currentParamsVar.value + def paramsScope[T](p: Parameters)(body: => T): T = { + currentParamsVar.withValue(p)(body) + } +} + +private object Builder { + // All global mutable state must be referenced via dynamicContextVar!! + private val dynamicContextVar = new DynamicVariable[Option[DynamicContext]](None) + + def dynamicContext = dynamicContextVar.value.get + def idGen = dynamicContext.idGen + def globalNamespace = dynamicContext.globalNamespace + def globalRefMap = dynamicContext.globalRefMap + def components = dynamicContext.components + def parameterDump = dynamicContext.parameterDump + + def pushCommand(c: Command) = dynamicContext.pushCommand(c) + def pushOp[T <: Data](cmd: DefPrim[T]) = { + pushCommand(cmd) + cmd.id + } + + def build[T <: Module](f: => T): Circuit = { + dynamicContextVar.withValue(Some(new DynamicContext)) { + val mod = f + globalRefMap.setRefForId(mod, mod.name) + Circuit(components.last.name, components, globalRefMap, parameterDump) + } + } +} diff --git a/src/main/scala/Chisel/Core.scala b/src/main/scala/Chisel/Core.scala index 03fc3040..7ef9c896 100644 --- a/src/main/scala/Chisel/Core.scala +++ b/src/main/scala/Chisel/Core.scala @@ -1,274 +1,29 @@ package Chisel -import scala.util.DynamicVariable import scala.collection.immutable.ListMap -import scala.collection.mutable.{ArrayBuffer, Stack, HashSet, HashMap, LinkedHashMap} +import scala.collection.mutable.{ArrayBuffer, HashSet, LinkedHashMap} import java.lang.reflect.Modifier._ import java.lang.Double.longBitsToDouble import java.lang.Float.intBitsToFloat - -private class IdGen { - private var counter = -1L - def next: Long = { - counter += 1 - counter - } -} - -class RefMap { - private val _refmap = new HashMap[Long,Immediate]() - - def setRef(id: Id, ref: Immediate): Unit = - _refmap(id._id) = ref - - def setRefForId(id: Id, name: String)(implicit namespace: Namespace = Builder.globalNamespace): Unit = - if (!_refmap.contains(id._id)) - setRef(id, Ref(namespace.name(name))) - - def setFieldForId(parentid: Id, id: Id, name: String): Unit = { - _refmap(id._id) = Slot(Alias(parentid), name) - } - - def setIndexForId(parentid: Id, id: Id, index: Int): Unit = - _refmap(id._id) = Index(Alias(parentid), index) - - def apply(id: Id): Immediate = _refmap(id._id) -} - -private class DynamicContext { - val idGen = new IdGen - val globalNamespace = new FIRRTLNamespace - val globalRefMap = new RefMap - val components = ArrayBuffer[Component]() - val currentModuleVar = new DynamicVariable[Option[Module]](None) - val currentParamsVar = new DynamicVariable[Parameters](Parameters.empty) - val parameterDump = new ParameterDump - - def getCurrentModule = currentModuleVar.value - def moduleScope[T](body: => T): T = { - currentModuleVar.withValue(getCurrentModule)(body) - } - def forceCurrentModule[T](m: Module) { // Used in Module constructor - currentModuleVar.value = Some(m) - } - def pushCommand(c: Command) { - currentModuleVar.value.foreach(_._commands += c) - } - - def getParams: Parameters = currentParamsVar.value - def paramsScope[T](p: Parameters)(body: => T): T = { - currentParamsVar.withValue(p)(body) - } -} - -private object Builder { - // All global mutable state must be referenced via dynamicContextVar!! - private val dynamicContextVar = new DynamicVariable[Option[DynamicContext]](None) - - def dynamicContext = dynamicContextVar.value.get - def idGen = dynamicContext.idGen - def globalNamespace = dynamicContext.globalNamespace - def globalRefMap = dynamicContext.globalRefMap - def components = dynamicContext.components - def parameterDump = dynamicContext.parameterDump - - def pushCommand(c: Command) = dynamicContext.pushCommand(c) - def pushOp[T <: Data](cmd: DefPrim[T]) = { - pushCommand(cmd) - cmd.id - } - - def build[T <: Module](f: => T): Circuit = { - dynamicContextVar.withValue(Some(new DynamicContext)) { - val mod = f - globalRefMap.setRefForId(mod, mod.name) - Circuit(components.last.name, components, globalRefMap, parameterDump) - } - } -} - import Builder.pushCommand import Builder.pushOp import Builder.dynamicContext - -/// CHISEL IR - -case class PrimOp(val name: String) { - override def toString = name -} - -object PrimOp { - val AddOp = PrimOp("add") - val AddModOp = PrimOp("addw") - val SubOp = PrimOp("sub") - val SubModOp = PrimOp("subw") - 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("and") - val BitOrOp = PrimOp("or") - val BitXorOp = PrimOp("xor") - val BitNotOp = PrimOp("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 PadOp = PrimOp("pad") - val NotEqualOp = PrimOp("neq") - val NegOp = PrimOp("neg") - val MultiplexOp = PrimOp("mux") - val XorReduceOp = PrimOp("xorr") - val ConvertOp = PrimOp("cvt") - val AsUIntOp = PrimOp("asUInt") - val AsSIntOp = PrimOp("asSInt") -} import PrimOp._ -abstract class Immediate { - def fullName(ctx: Component): String = name - def name: String -} - -abstract class Arg extends Immediate { - def name: String -} +object Literal { + def sizeof(x: BigInt): Int = x.bitLength -case class Alias(id: Id) extends Arg { - private val refMap = Builder.globalRefMap - override def fullName(ctx: Component) = refMap(id).fullName(ctx) - def name = refMap(id).name - def emit: String = s"Alias($id)" -} - -abstract class LitArg(val num: BigInt, widthArg: Width) extends Arg { - private[Chisel] def forcedWidth = widthArg.known - private[Chisel] def width: Width = if (forcedWidth) widthArg else Width(minWidth) - - protected def minWidth: Int - if (forcedWidth) - require(widthArg.get >= minWidth) -} - -case class ILit(n: BigInt) extends Arg { - def name = n.toString -} - -case class ULit(n: BigInt, w: Width) extends LitArg(n, w) { - def name = "UInt<" + width + ">(\"h0" + num.toString(16) + "\")" - def minWidth = 1 max n.bitLength - - require(n >= 0, s"UInt literal ${n} is negative") -} - -case class SLit(n: BigInt, w: Width) extends LitArg(n, w) { - def name = { - val unsigned = if (n < 0) (BigInt(1) << width.get) + n else n - s"asSInt(${ULit(unsigned, width).name})" + def decodeBase(base: Char): Int = base match { + case 'x' | 'h' => 16 + case 'd' => 10 + case 'o' => 8 + case 'b' => 2 + case _ => ChiselError.error("Invalid base " + base); 2 } - def minWidth = 1 + n.bitLength -} -case class Ref(name: String) extends Immediate -case class ModuleIO(mod: Module) extends Immediate { - private val refMap = Builder.globalRefMap - def name = refMap(mod).name - override def fullName(ctx: Component) = if (mod eq ctx.id) "" else name -} -case class Slot(imm: Alias, name: String) extends Immediate { - override def fullName(ctx: Component) = - if (imm.fullName(ctx).isEmpty) name - else s"${imm.fullName(ctx)}.${name}" -} -case class Index(imm: Immediate, value: Int) extends Immediate { - def name = s"[$value]" - override def fullName(ctx: Component) = s"${imm.fullName(ctx)}[$value]" -} - -case class Port(id: Data, kind: Kind) - -object Width { - def apply(x: Int): Width = KnownWidth(x) - def apply(): Width = UnknownWidth() -} - -sealed abstract class Width { - type W = Int - def max(that: Width): Width = this.op(that, _ max _) - def + (that: Width): Width = this.op(that, _ + _) - def + (that: Int): Width = this.op(this, (a, b) => a + that) - def shiftRight(that: Int): Width = this.op(this, (a, b) => 0 max (a - that)) - def dynamicShiftLeft(that: Width): Width = - this.op(that, (a, b) => a + (1 << b) - 1) - - def known: Boolean - def get: W - protected def op(that: Width, f: (W, W) => W): Width -} - -sealed case class UnknownWidth() extends Width { - def known = false - def get = None.get - def op(that: Width, f: (W, W) => W) = this - override def toString = "?" -} - -sealed case class KnownWidth(value: Int) extends Width { - require(value >= 0) - def known = true - def get = value - def op(that: Width, f: (W, W) => W) = that match { - case KnownWidth(x) => KnownWidth(f(value, x)) - case _ => that - } - override def toString = value.toString + def stringToVal(base: Char, x: String): BigInt = + BigInt(x, decodeBase(base)) } -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: Seq[Port], flip: Boolean) extends Kind(flip); -case class VectorType(val size: Int, val kind: Kind, flip: Boolean) extends Kind(flip); -case class ClockType(flip: Boolean) extends Kind(flip) - -abstract class Command; -abstract class Definition extends Command { - private val refMap = Builder.globalRefMap - def id: Id - def name = refMap(id).name -} -case class DefFlo(id: Id, value: Float) extends Definition -case class DefDbl(id: Id, value: Double) extends Definition -case class DefPrim[T <: Data](id: T, op: PrimOp, args: Arg*) extends Definition -case class DefWire(id: Id, kind: Kind) extends Definition -case class DefRegister(id: Id, kind: Kind, clock: Arg, reset: Arg) extends Definition -case class DefMemory(id: Id, kind: Kind, size: Int, clock: Arg) extends Definition -case class DefSeqMemory(id: Id, kind: Kind, size: Int) extends Definition -case class DefAccessor(id: Id, source: Alias, direction: Direction, index: Arg) extends Definition -case class DefInstance(id: Module, ports: Seq[Port]) extends Definition -case class WhenBegin(pred: Arg) extends Command -case class WhenElse() extends Command -case class WhenEnd() extends Command -case class Connect(loc: Alias, exp: Arg) extends Command -case class BulkConnect(loc1: Alias, loc2: Alias) extends Command -case class ConnectInit(loc: Alias, exp: Arg) extends Command -case class Component(id: Module, name: String, ports: Seq[Port], commands: Seq[Command]) extends Immediate - -case class Circuit(name: String, components: Seq[Component], refMap: RefMap, parameterDump: ParameterDump) { - def emit = new Emitter(this).toString -} - -/// COMPONENTS - sealed abstract class Direction(name: String) { override def toString = name def flip: Direction @@ -277,8 +32,6 @@ object INPUT extends Direction("input") { def flip = OUTPUT } object OUTPUT extends Direction("output") { def flip = INPUT } object NO_DIR extends Direction("?") { def flip = NO_DIR } -/// CHISEL FRONT-END - trait Id { private[Chisel] val _id = Builder.idGen.next } @@ -1076,85 +829,3 @@ class WhenContext(cond: => Bool)(block: => Unit) { res } } - - -/// CHISEL IR EMITTER - -class Emitter(circuit: Circuit) { - override def toString = res.toString - - def join(parts: Seq[String], sep: String): StringBuilder = - parts.tail.foldLeft(new StringBuilder(parts.head))((s, p) => s ++= sep ++= p) - def emitDir(e: Port, isTop: Boolean): String = - if (isTop) (if (e.id.isFlip) "input " else "output ") - else (if (e.id.isFlip) "flip " else "") - def emitPort(e: Port, isTop: Boolean): String = - s"${emitDir(e, isTop)}${circuit.refMap(e.id).name} : ${emitType(e.kind)}" - private def emitType(e: Kind): String = e match { - case e: UnknownType => "?" - case e: UIntType => s"UInt<${e.width}>" - case e: SIntType => s"SInt<${e.width}>" - case e: BundleType => s"{${join(e.ports.map(x => emitPort(x, false)), ", ")}}" - case e: VectorType => s"${emitType(e.kind)}[${e.size}]" - case e: ClockType => s"Clock" - } - private def emit(e: Command, ctx: Component): String = e match { - case e: DefFlo => s"node ${e.name} = Flo(${e.value})" - case e: DefDbl => s"node ${e.name} = Dbl(${e.value})" - case e: DefPrim[_] => s"node ${e.name} = ${e.op.name}(${join(e.args.map(x => x.fullName(ctx)), ", ")})" - case e: DefWire => s"wire ${e.name} : ${emitType(e.kind)}" - case e: DefRegister => s"reg ${e.name} : ${emitType(e.kind)}, ${e.clock.fullName(ctx)}, ${e.reset.fullName(ctx)}" - case e: DefMemory => s"cmem ${e.name} : ${emitType(e.kind)}[${e.size}], ${e.clock.fullName(ctx)}"; - case e: DefSeqMemory => s"smem ${e.name} : ${emitType(e.kind)}[${e.size}]"; - case e: DefAccessor => s"infer accessor ${e.name} = ${e.source.fullName(ctx)}[${e.index.fullName(ctx)}]" - case e: Connect => s"${e.loc.fullName(ctx)} := ${e.exp.fullName(ctx)}" - case e: BulkConnect => s"${e.loc1.fullName(ctx)} <> ${e.loc2.fullName(ctx)}" - case e: ConnectInit => s"onreset ${e.loc.fullName(ctx)} := ${e.exp.fullName(ctx)}" - case e: DefInstance => { - val res = new StringBuilder(s"inst ${e.name} of ${e.id.name}") - res ++= newline - for (p <- e.ports; x <- initPort(p, INPUT, ctx)) - res ++= newline + x - res.toString - } - - case w: WhenBegin => - indent() - s"when ${w.pred.fullName(ctx)} :" - case _: WhenElse => - indent() - "else :" - case _: WhenEnd => - unindent() - "skip" - } - private def initPort(p: Port, dir: Direction, ctx: Component) = { - for (x <- p.id.flatten; if x.dir == dir) - yield s"${circuit.refMap(x).fullName(ctx)} := ${x.makeLit(0).name}" - } - - private def emit(m: Component): Unit = { - res ++= newline + s"module ${m.name} : " - withIndent { - for (p <- m.ports) - res ++= newline + emitPort(p, true) - res ++= newline - for (p <- m.ports; x <- initPort(p, OUTPUT, m)) - res ++= newline + x - res ++= newline - for (cmd <- m.commands) - res ++= newline + emit(cmd, m) - res ++= newline - } - } - - private var indentLevel = 0 - private def newline = "\n" + (" " * indentLevel) - private def indent(): Unit = indentLevel += 1 - private def unindent() { require(indentLevel > 0); indentLevel -= 1 } - private def withIndent(f: => Unit) { indent(); f; unindent() } - - private val res = new StringBuilder(s"circuit ${circuit.name} : ") - withIndent { circuit.components foreach emit } - res ++= newline -} diff --git a/src/main/scala/Chisel/Emitter.scala b/src/main/scala/Chisel/Emitter.scala new file mode 100644 index 00000000..0e75c9a9 --- /dev/null +++ b/src/main/scala/Chisel/Emitter.scala @@ -0,0 +1,80 @@ +package Chisel + +class Emitter(circuit: Circuit) { + override def toString = res.toString + + def join(parts: Seq[String], sep: String): StringBuilder = + parts.tail.foldLeft(new StringBuilder(parts.head))((s, p) => s ++= sep ++= p) + def emitDir(e: Port, isTop: Boolean): String = + if (isTop) (if (e.id.isFlip) "input " else "output ") + else (if (e.id.isFlip) "flip " else "") + def emitPort(e: Port, isTop: Boolean): String = + s"${emitDir(e, isTop)}${circuit.refMap(e.id).name} : ${emitType(e.kind)}" + private def emitType(e: Kind): String = e match { + case e: UnknownType => "?" + case e: UIntType => s"UInt<${e.width}>" + case e: SIntType => s"SInt<${e.width}>" + case e: BundleType => s"{${join(e.ports.map(x => emitPort(x, false)), ", ")}}" + case e: VectorType => s"${emitType(e.kind)}[${e.size}]" + case e: ClockType => s"Clock" + } + private def emit(e: Command, ctx: Component): String = e match { + case e: DefFlo => s"node ${e.name} = Flo(${e.value})" + case e: DefDbl => s"node ${e.name} = Dbl(${e.value})" + case e: DefPrim[_] => s"node ${e.name} = ${e.op.name}(${join(e.args.map(x => x.fullName(ctx)), ", ")})" + case e: DefWire => s"wire ${e.name} : ${emitType(e.kind)}" + case e: DefRegister => s"reg ${e.name} : ${emitType(e.kind)}, ${e.clock.fullName(ctx)}, ${e.reset.fullName(ctx)}" + case e: DefMemory => s"cmem ${e.name} : ${emitType(e.kind)}[${e.size}], ${e.clock.fullName(ctx)}"; + case e: DefSeqMemory => s"smem ${e.name} : ${emitType(e.kind)}[${e.size}]"; + case e: DefAccessor => s"infer accessor ${e.name} = ${e.source.fullName(ctx)}[${e.index.fullName(ctx)}]" + case e: Connect => s"${e.loc.fullName(ctx)} := ${e.exp.fullName(ctx)}" + case e: BulkConnect => s"${e.loc1.fullName(ctx)} <> ${e.loc2.fullName(ctx)}" + case e: ConnectInit => s"onreset ${e.loc.fullName(ctx)} := ${e.exp.fullName(ctx)}" + case e: DefInstance => { + val res = new StringBuilder(s"inst ${e.name} of ${e.id.name}") + res ++= newline + for (p <- e.ports; x <- initPort(p, INPUT, ctx)) + res ++= newline + x + res.toString + } + + case w: WhenBegin => + indent() + s"when ${w.pred.fullName(ctx)} :" + case _: WhenElse => + indent() + "else :" + case _: WhenEnd => + unindent() + "skip" + } + private def initPort(p: Port, dir: Direction, ctx: Component) = { + for (x <- p.id.flatten; if x.dir == dir) + yield s"${circuit.refMap(x).fullName(ctx)} := ${x.makeLit(0).name}" + } + + private def emit(m: Component): Unit = { + res ++= newline + s"module ${m.name} : " + withIndent { + for (p <- m.ports) + res ++= newline + emitPort(p, true) + res ++= newline + for (p <- m.ports; x <- initPort(p, OUTPUT, m)) + res ++= newline + x + res ++= newline + for (cmd <- m.commands) + res ++= newline + emit(cmd, m) + res ++= newline + } + } + + private var indentLevel = 0 + private def newline = "\n" + (" " * indentLevel) + private def indent(): Unit = indentLevel += 1 + private def unindent() { require(indentLevel > 0); indentLevel -= 1 } + private def withIndent(f: => Unit) { indent(); f; unindent() } + + private val res = new StringBuilder(s"circuit ${circuit.name} : ") + withIndent { circuit.components foreach emit } + res ++= newline +} diff --git a/src/main/scala/Chisel/Enum.scala b/src/main/scala/Chisel/Enum.scala deleted file mode 100644 index 7072be0c..00000000 --- a/src/main/scala/Chisel/Enum.scala +++ /dev/null @@ -1,43 +0,0 @@ -/* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of - California (Regents). All Rights Reserved. Redistribution and use in - source and binary forms, with or without modification, are permitted - provided that the following conditions are met: - - * Redistributions of source code must retain the above - copyright notice, this list of conditions and the following - two paragraphs of disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - two paragraphs of disclaimer in the documentation and/or other materials - provided with the distribution. - * Neither the name of the Regents nor the names of its contributors - may be used to endorse or promote products derived from this - software without specific prior written permission. - - IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, - SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, - ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF - REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF - ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION - TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR - MODIFICATIONS. -*/ - -package Chisel -import Literal._ - -object Enum { - /** create n enum values of given type */ - def apply[T <: Bits](nodeType: T, n: Int): List[T] = Range(0, n).map(x => nodeType.fromInt(x)).toList - - /** create enum values of given type and names */ - def apply[T <: Bits](nodeType: T, l: Symbol *): Map[Symbol, T] = (l.toList zip (Range(0, l.length).map(x => nodeType.fromInt(x)))).toMap - - /** create enum values of given type and names */ - def apply[T <: Bits](nodeType: T, l: List[Symbol]): Map[Symbol, T] = (l zip (Range(0, l.length).map(x => nodeType.fromInt(x)))).toMap -} diff --git a/src/main/scala/Chisel/IR.scala b/src/main/scala/Chisel/IR.scala new file mode 100644 index 00000000..b543606c --- /dev/null +++ b/src/main/scala/Chisel/IR.scala @@ -0,0 +1,175 @@ +package Chisel + +case class PrimOp(val name: String) { + override def toString = name +} + +object PrimOp { + val AddOp = PrimOp("add") + val AddModOp = PrimOp("addw") + val SubOp = PrimOp("sub") + val SubModOp = PrimOp("subw") + 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("and") + val BitOrOp = PrimOp("or") + val BitXorOp = PrimOp("xor") + val BitNotOp = PrimOp("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 PadOp = PrimOp("pad") + val NotEqualOp = PrimOp("neq") + val NegOp = PrimOp("neg") + val MultiplexOp = PrimOp("mux") + val XorReduceOp = PrimOp("xorr") + val ConvertOp = PrimOp("cvt") + val AsUIntOp = PrimOp("asUInt") + val AsSIntOp = PrimOp("asSInt") +} + +abstract class Immediate { + def fullName(ctx: Component): String = name + def name: String +} + +abstract class Arg extends Immediate { + def name: String +} + +case class Alias(id: Id) extends Arg { + private val refMap = Builder.globalRefMap + override def fullName(ctx: Component) = refMap(id).fullName(ctx) + def name = refMap(id).name + def emit: String = s"Alias($id)" +} + +abstract class LitArg(val num: BigInt, widthArg: Width) extends Arg { + private[Chisel] def forcedWidth = widthArg.known + private[Chisel] def width: Width = if (forcedWidth) widthArg else Width(minWidth) + + protected def minWidth: Int + if (forcedWidth) + require(widthArg.get >= minWidth) +} + +case class ILit(n: BigInt) extends Arg { + def name = n.toString +} + +case class ULit(n: BigInt, w: Width) extends LitArg(n, w) { + def name = "UInt<" + width + ">(\"h0" + num.toString(16) + "\")" + def minWidth = 1 max n.bitLength + + require(n >= 0, s"UInt literal ${n} is negative") +} + +case class SLit(n: BigInt, w: Width) extends LitArg(n, w) { + def name = { + val unsigned = if (n < 0) (BigInt(1) << width.get) + n else n + s"asSInt(${ULit(unsigned, width).name})" + } + def minWidth = 1 + n.bitLength +} + +case class Ref(name: String) extends Immediate +case class ModuleIO(mod: Module) extends Immediate { + private val refMap = Builder.globalRefMap + def name = refMap(mod).name + override def fullName(ctx: Component) = if (mod eq ctx.id) "" else name +} +case class Slot(imm: Alias, name: String) extends Immediate { + override def fullName(ctx: Component) = + if (imm.fullName(ctx).isEmpty) name + else s"${imm.fullName(ctx)}.${name}" +} +case class Index(imm: Immediate, value: Int) extends Immediate { + def name = s"[$value]" + override def fullName(ctx: Component) = s"${imm.fullName(ctx)}[$value]" +} + +case class Port(id: Data, kind: Kind) + +object Width { + def apply(x: Int): Width = KnownWidth(x) + def apply(): Width = UnknownWidth() +} + +sealed abstract class Width { + type W = Int + def max(that: Width): Width = this.op(that, _ max _) + def + (that: Width): Width = this.op(that, _ + _) + def + (that: Int): Width = this.op(this, (a, b) => a + that) + def shiftRight(that: Int): Width = this.op(this, (a, b) => 0 max (a - that)) + def dynamicShiftLeft(that: Width): Width = + this.op(that, (a, b) => a + (1 << b) - 1) + + def known: Boolean + def get: W + protected def op(that: Width, f: (W, W) => W): Width +} + +sealed case class UnknownWidth() extends Width { + def known = false + def get = None.get + def op(that: Width, f: (W, W) => W) = this + override def toString = "?" +} + +sealed case class KnownWidth(value: Int) extends Width { + require(value >= 0) + def known = true + def get = value + def op(that: Width, f: (W, W) => W) = that match { + case KnownWidth(x) => KnownWidth(f(value, x)) + case _ => that + } + override def toString = value.toString +} + +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: Seq[Port], flip: Boolean) extends Kind(flip); +case class VectorType(val size: Int, val kind: Kind, flip: Boolean) extends Kind(flip); +case class ClockType(flip: Boolean) extends Kind(flip) + +abstract class Command; +abstract class Definition extends Command { + private val refMap = Builder.globalRefMap + def id: Id + def name = refMap(id).name +} +case class DefFlo(id: Id, value: Float) extends Definition +case class DefDbl(id: Id, value: Double) extends Definition +case class DefPrim[T <: Data](id: T, op: PrimOp, args: Arg*) extends Definition +case class DefWire(id: Id, kind: Kind) extends Definition +case class DefRegister(id: Id, kind: Kind, clock: Arg, reset: Arg) extends Definition +case class DefMemory(id: Id, kind: Kind, size: Int, clock: Arg) extends Definition +case class DefSeqMemory(id: Id, kind: Kind, size: Int) extends Definition +case class DefAccessor(id: Id, source: Alias, direction: Direction, index: Arg) extends Definition +case class DefInstance(id: Module, ports: Seq[Port]) extends Definition +case class WhenBegin(pred: Arg) extends Command +case class WhenElse() extends Command +case class WhenEnd() extends Command +case class Connect(loc: Alias, exp: Arg) extends Command +case class BulkConnect(loc1: Alias, loc2: Alias) extends Command +case class ConnectInit(loc: Alias, exp: Arg) extends Command +case class Component(id: Module, name: String, ports: Seq[Port], commands: Seq[Command]) extends Immediate + +case class Circuit(name: String, components: Seq[Component], refMap: RefMap, parameterDump: ParameterDump) { + def emit = new Emitter(this).toString +} diff --git a/src/main/scala/Chisel/Literal.scala b/src/main/scala/Chisel/Literal.scala deleted file mode 100644 index a8e28103..00000000 --- a/src/main/scala/Chisel/Literal.scala +++ /dev/null @@ -1,16 +0,0 @@ -package Chisel - -object Literal { - def sizeof(x: BigInt): Int = x.bitLength - - def decodeBase(base: Char): Int = base match { - case 'x' | 'h' => 16 - case 'd' => 10 - case 'o' => 8 - case 'b' => 2 - case _ => ChiselError.error("Invalid base " + base); 2 - } - - def stringToVal(base: Char, x: String): BigInt = - BigInt(x, decodeBase(base)) -} diff --git a/src/main/scala/Chisel/Log2.scala b/src/main/scala/Chisel/Log2.scala deleted file mode 100644 index 01b081ef..00000000 --- a/src/main/scala/Chisel/Log2.scala +++ /dev/null @@ -1,35 +0,0 @@ -package Chisel - -// TODO: these operators should be backend nodes so their width can be -// inferred, rather than using getWidth. also, C++ perf would improve. - -object Log2 { - def apply(x: Bits, width: Int): UInt = { - if (width < 2) UInt(0) - else if (width == 2) x(1) - else Mux(x(width-1), UInt(width-1), apply(x, width-1)) - } - - def apply(x: Bits): UInt = apply(x, x.getWidth) -} - -object OHToUInt { - def apply(in: Seq[Bool]): UInt = apply(Vec(in)) - def apply(in: Vec[Bool]): UInt = apply(in.toBits, in.size) - def apply(in: Bits): UInt = apply(in, in.getWidth) - - def apply(in: Bits, width: Int): UInt = { - if (width <= 2) Log2(in, width) - else { - val mid = 1 << (log2Up(width)-1) - val hi = in(width-1, mid) - val lo = in(mid-1, 0) - Cat(hi.orR, apply(hi | lo, mid)) - } - } -} - -object PriorityEncoder { - def apply(in: Seq[Bool]): UInt = PriorityMux(in, (0 until in.size).map(UInt(_))) - def apply(in: Bits): UInt = apply(in.toBools) -} diff --git a/src/main/scala/Chisel/Utils.scala b/src/main/scala/Chisel/Utils.scala index a7c60677..be675da5 100644 --- a/src/main/scala/Chisel/Utils.scala +++ b/src/main/scala/Chisel/Utils.scala @@ -6,6 +6,17 @@ import scala.language.experimental.macros import scala.reflect.runtime.universe._ import scala.reflect.macros.blackbox._ +object Enum { + /** create n enum values of given type */ + def apply[T <: Bits](nodeType: T, n: Int): List[T] = Range(0, n).map(x => nodeType.fromInt(x)).toList + + /** create enum values of given type and names */ + def apply[T <: Bits](nodeType: T, l: Symbol *): Map[Symbol, T] = (l.toList zip (Range(0, l.length).map(x => nodeType.fromInt(x)))).toMap + + /** create enum values of given type and names */ + def apply[T <: Bits](nodeType: T, l: List[Symbol]): Map[Symbol, T] = (l zip (Range(0, l.length).map(x => nodeType.fromInt(x)))).toMap +} + object log2Up { def apply(in: Int): Int = 1 max BigInt(in-1).bitLength } @@ -247,6 +258,36 @@ object ShiftRegister } } +object Log2 { + def apply(x: Bits, width: Int): UInt = { + if (width < 2) UInt(0) + else if (width == 2) x(1) + else Mux(x(width-1), UInt(width-1), apply(x, width-1)) + } + + def apply(x: Bits): UInt = apply(x, x.getWidth) +} + +object OHToUInt { + def apply(in: Seq[Bool]): UInt = apply(Vec(in)) + def apply(in: Vec[Bool]): UInt = apply(in.toBits, in.size) + def apply(in: Bits): UInt = apply(in, in.getWidth) + + def apply(in: Bits, width: Int): UInt = { + if (width <= 2) Log2(in, width) + else { + val mid = 1 << (log2Up(width)-1) + val hi = in(width-1, mid) + val lo = in(mid-1, 0) + Cat(hi.orR, apply(hi | lo, mid)) + } + } +} + +object PriorityEncoder { + def apply(in: Seq[Bool]): UInt = PriorityMux(in, (0 until in.size).map(UInt(_))) + def apply(in: Bits): UInt = apply(in.toBools) +} /** Returns the one hot encoding of the input UInt. */ object UIntToOH |
