diff options
Diffstat (limited to 'src/main/scala/Chisel')
| -rw-r--r-- | src/main/scala/Chisel/Bits.scala | 50 | ||||
| -rw-r--r-- | src/main/scala/Chisel/Data.scala | 10 | ||||
| -rw-r--r-- | src/main/scala/Chisel/Driver.scala | 3 | ||||
| -rw-r--r-- | src/main/scala/Chisel/FileSystemUtilities.scala | 10 | ||||
| -rw-r--r-- | src/main/scala/Chisel/Main.scala | 8 | ||||
| -rw-r--r-- | src/main/scala/Chisel/Mem.scala | 7 | ||||
| -rw-r--r-- | src/main/scala/Chisel/Module.scala | 8 | ||||
| -rw-r--r-- | src/main/scala/Chisel/Reg.scala | 10 | ||||
| -rw-r--r-- | src/main/scala/Chisel/internal/firrtl/Emitter.scala | 69 | ||||
| -rw-r--r-- | src/main/scala/Chisel/internal/firrtl/IR.scala | 12 | ||||
| -rw-r--r-- | src/main/scala/Chisel/throwException.scala | 11 |
11 files changed, 138 insertions, 60 deletions
diff --git a/src/main/scala/Chisel/Bits.scala b/src/main/scala/Chisel/Bits.scala index fbc1586f..b800644d 100644 --- a/src/main/scala/Chisel/Bits.scala +++ b/src/main/scala/Chisel/Bits.scala @@ -29,6 +29,24 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg: override def <> (that: Data): Unit = this := that + def tail(n: Int): UInt = { + val w = width match { + case KnownWidth(x) => + require(x >= n, s"Can't tail($n) for width $x < $n") + Width(x - n) + case UnknownWidth() => Width() + } + binop(UInt(width = w), TailOp, n) + } + + def head(n: Int): UInt = { + width match { + case KnownWidth(x) => require(x >= n, s"Can't head($n) for width $x < $n") + case UnknownWidth() => + } + binop(UInt(width = n), HeadOp, n) + } + /** Returns the specified bit on this wire as a [[Bool]], statically * addressed. */ @@ -39,7 +57,7 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg: if (isLit()) { Bool(((litValue() >> x.toInt) & 1) == 1) } else { - pushOp(DefPrim(Bool(), BitSelectOp, this.ref, ILit(x))) + pushOp(DefPrim(Bool(), BitsExtractOp, this.ref, ILit(x), ILit(x))) } } @@ -92,9 +110,6 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg: private[Chisel] def redop(op: PrimOp): Bool = pushOp(DefPrim(Bool(), op, this.ref)) - /** Returns this wire bitwise-inverted. */ - def unary_~ : this.type = unop(cloneTypeWidth(width), BitNotOp) - /** Returns this wire zero padded up to the specified width. * * @note for SInts only, this does sign extension @@ -279,19 +294,22 @@ sealed class UInt private[Chisel] (dir: Direction, width: Width, lit: Option[ULi def unary_-% : UInt = UInt(0) -% this def +& (other: UInt): UInt = binop(UInt((this.width max other.width) + 1), AddOp, other) def + (other: UInt): UInt = this +% other - def +% (other: UInt): UInt = binop(UInt(this.width max other.width), AddModOp, other) + def +% (other: UInt): UInt = (this +& other) tail 1 def -& (other: UInt): UInt = binop(UInt((this.width max other.width) + 1), SubOp, other) def - (other: UInt): UInt = this -% other - def -% (other: UInt): UInt = binop(UInt(this.width max other.width), SubModOp, other) + def -% (other: UInt): UInt = (this -& other) tail 1 def * (other: UInt): UInt = binop(UInt(this.width + other.width), TimesOp, other) def * (other: SInt): SInt = other * this def / (other: UInt): UInt = binop(UInt(this.width), DivideOp, other) - def % (other: UInt): UInt = binop(UInt(this.width), ModOp, other) + def % (other: UInt): UInt = binop(UInt(this.width), RemOp, other) def & (other: UInt): UInt = binop(UInt(this.width max other.width), BitAndOp, other) def | (other: UInt): UInt = binop(UInt(this.width max other.width), BitOrOp, other) def ^ (other: UInt): UInt = binop(UInt(this.width max other.width), BitXorOp, other) + /** Returns this wire bitwise-inverted. */ + def unary_~ : UInt = unop(UInt(width = width), BitNotOp) + // REVIEW TODO: Can this be defined on Bits? def orR: Bool = this != UInt(0) def andR: Bool = ~this === UInt(0) @@ -410,21 +428,24 @@ sealed class SInt private (dir: Direction, width: Width, lit: Option[SLit] = Non /** add (default - no growth) operator */ def + (other: SInt): SInt = this +% other /** add (no growth) operator */ - def +% (other: SInt): SInt = binop(SInt(this.width max other.width), AddModOp, other) + def +% (other: SInt): SInt = (this +& other).tail(1).asSInt /** subtract (width +1) operator */ def -& (other: SInt): SInt = binop(SInt((this.width max other.width) + 1), SubOp, other) /** subtract (default - no growth) operator */ def - (other: SInt): SInt = this -% other /** subtract (no growth) operator */ - def -% (other: SInt): SInt = binop(SInt(this.width max other.width), SubModOp, other) + def -% (other: SInt): SInt = (this -& other).tail(1).asSInt def * (other: SInt): SInt = binop(SInt(this.width + other.width), TimesOp, other) def * (other: UInt): SInt = binop(SInt(this.width + other.width), TimesOp, other) def / (other: SInt): SInt = binop(SInt(this.width), DivideOp, other) - def % (other: SInt): SInt = binop(SInt(this.width), ModOp, other) + def % (other: SInt): SInt = binop(SInt(this.width), RemOp, other) - def & (other: SInt): SInt = binop(SInt(this.width max other.width), BitAndOp, other) - def | (other: SInt): SInt = binop(SInt(this.width max other.width), BitOrOp, other) - def ^ (other: SInt): SInt = binop(SInt(this.width max other.width), BitXorOp, other) + def & (other: SInt): SInt = binop(UInt(this.width max other.width), BitAndOp, other).asSInt + def | (other: SInt): SInt = binop(UInt(this.width max other.width), BitOrOp, other).asSInt + def ^ (other: SInt): SInt = binop(UInt(this.width max other.width), BitXorOp, other).asSInt + + /** Returns this wire bitwise-inverted. */ + def unary_~ : SInt = unop(UInt(width = width), BitNotOp).asSInt def < (other: SInt): Bool = compop(LessOp, other) def > (other: SInt): Bool = compop(GreaterOp, other) @@ -490,6 +511,9 @@ sealed class Bool(dir: Direction, lit: Option[ULit] = None) extends UInt(dir, Wi def | (other: Bool): Bool = binop(Bool(), BitOrOp, other) def ^ (other: Bool): Bool = binop(Bool(), BitXorOp, other) + /** Returns this wire bitwise-inverted. */ + override def unary_~ : Bool = unop(Bool(), BitNotOp) + /** Outputs the logical OR of two Bools. */ def || (that: Bool): Bool = this | that diff --git a/src/main/scala/Chisel/Data.scala b/src/main/scala/Chisel/Data.scala index 1011fe47..0ac3ee32 100644 --- a/src/main/scala/Chisel/Data.scala +++ b/src/main/scala/Chisel/Data.scala @@ -119,7 +119,7 @@ object Wire { if (init != null) { x := init } else { - x.flatten.foreach(e => e := e.fromInt(0)) + pushCommand(DefInvalid(x.ref)) } x } @@ -141,11 +141,3 @@ sealed class Clock(dirArg: Direction) extends Element(dirArg, Width(1)) { case _ => this badConnect that } } - -// TODO: check with FIRRTL specs, how much official implementation flexibility -// is there? -/** A source of garbage data, used to initialize Wires to a don't-care value. */ -private object Poison extends Command { - def apply[T <: Data](t: T): T = - pushCommand(DefPoison(t.cloneType)).id -} diff --git a/src/main/scala/Chisel/Driver.scala b/src/main/scala/Chisel/Driver.scala index 6a5e2095..a6f61f69 100644 --- a/src/main/scala/Chisel/Driver.scala +++ b/src/main/scala/Chisel/Driver.scala @@ -113,4 +113,7 @@ object Driver extends BackendCompilationUtilities { w.close() f } + + // FIXME: This is hard coded and should come in from a command-line argument + def targetDir(): String = { "vsim/generated-src" } } diff --git a/src/main/scala/Chisel/FileSystemUtilities.scala b/src/main/scala/Chisel/FileSystemUtilities.scala new file mode 100644 index 00000000..efb7178d --- /dev/null +++ b/src/main/scala/Chisel/FileSystemUtilities.scala @@ -0,0 +1,10 @@ +// See LICENSE for details + +package Chisel + +@deprecated("FileSystemUtilities doesn't exist in chisel3", "3.0.0") +trait FileSystemUtilities { + def createOutputFile(name: String) = { + new java.io.FileWriter(Driver.targetDir + "/" + name) + } +} diff --git a/src/main/scala/Chisel/Main.scala b/src/main/scala/Chisel/Main.scala index 23abc763..750e8712 100644 --- a/src/main/scala/Chisel/Main.scala +++ b/src/main/scala/Chisel/Main.scala @@ -2,7 +2,15 @@ package Chisel +import java.io.File + @deprecated("chiselMain doesn't exist in Chisel3", "3.0") object chiselMain { def apply[T <: Module](args: Array[String], gen: () => T) = Predef.assert(false) + + def run[T <: Module] (args: Array[String], gen: () => T) = { + def circuit = Driver.elaborate(gen) + def output_file = new File(Driver.targetDir + "/" + circuit.name + ".fir") + Driver.dumpFirrtl(circuit, Option(output_file)) + } } diff --git a/src/main/scala/Chisel/Mem.scala b/src/main/scala/Chisel/Mem.scala index 3bbb1151..21284607 100644 --- a/src/main/scala/Chisel/Mem.scala +++ b/src/main/scala/Chisel/Mem.scala @@ -113,6 +113,9 @@ object SeqMem { * result is undefined (unlike Vec, where the last assignment wins) */ sealed class SeqMem[T <: Data](t: T, n: Int) extends MemBase[T](t, n) { - def read(addr: UInt, enable: Bool): T = - read(Mux(enable, addr, Poison(addr))) + def read(addr: UInt, enable: Bool): T = { + val a = Wire(UInt()) + when (enable) { a := addr } + read(a) + } } diff --git a/src/main/scala/Chisel/Module.scala b/src/main/scala/Chisel/Module.scala index 2a0f29db..463c2f81 100644 --- a/src/main/scala/Chisel/Module.scala +++ b/src/main/scala/Chisel/Module.scala @@ -20,16 +20,12 @@ object Module { def apply[T <: Module](bc: => T): T = { val parent = dynamicContext.currentModule val m = bc.setRefs() - // init module outputs - m._commands prependAll (for (p <- m.io.flatten; if p.dir == OUTPUT) - yield Connect(p.lref, p.fromInt(0).ref)) + m._commands.prepend(DefInvalid(m.io.ref)) // init module outputs dynamicContext.currentModule = parent val ports = m.computePorts Builder.components += Component(m, m.name, ports, m._commands) pushCommand(DefInstance(m, ports)) - // init instance inputs - for (p <- m.io.flatten; if p.dir == INPUT) - p := p.fromInt(0) + pushCommand(DefInvalid(m.io.ref)) // init instance inputs m.connectImplicitIOs() } } diff --git a/src/main/scala/Chisel/Reg.scala b/src/main/scala/Chisel/Reg.scala index f166c84b..e69061c5 100644 --- a/src/main/scala/Chisel/Reg.scala +++ b/src/main/scala/Chisel/Reg.scala @@ -45,10 +45,12 @@ object Reg { // to resolve all use cases. If the type inferencer / implicit resolution // system improves, this may be changed. val x = makeType(t, next, init) - val (resetEn, resetVal) = - if (init != null) (Node(x._parent.get.reset), init) - else (ULit(0, Width(1)), x) - pushCommand(DefRegister(x, Node(x._parent.get.clock), resetEn, resetVal.ref)) // TODO multi-clock + val clock = Node(x._parent.get.clock) // TODO multi-clock + if (init == null) { + pushCommand(DefReg(x, clock)) + } else { + pushCommand(DefRegInit(x, clock, Node(x._parent.get.reset), init.ref)) + } if (next != null) { x := next } diff --git a/src/main/scala/Chisel/internal/firrtl/Emitter.scala b/src/main/scala/Chisel/internal/firrtl/Emitter.scala index 8597454a..c2391f97 100644 --- a/src/main/scala/Chisel/internal/firrtl/Emitter.scala +++ b/src/main/scala/Chisel/internal/firrtl/Emitter.scala @@ -11,8 +11,8 @@ private class Emitter(circuit: Circuit) { private def emit(e: Command, ctx: Component): String = e match { case e: DefPrim[_] => s"node ${e.name} = ${e.op.name}(${e.args.map(_.fullName(ctx)).reduce(_ + ", " + _)})" case e: DefWire => s"wire ${e.name} : ${e.id.toType}" - case e: DefPoison[_] => s"poison ${e.name} : ${e.id.toType}" - case e: DefRegister => s"reg ${e.name} : ${e.id.toType}, ${e.clock.fullName(ctx)}, ${e.reset.fullName(ctx)}, ${e.init.fullName(ctx)}" + case e: DefReg => s"reg ${e.name} : ${e.id.toType}, ${e.clock.fullName(ctx)}" + case e: DefRegInit => s"reg ${e.name} : ${e.id.toType}, ${e.clock.fullName(ctx)} with : (reset => (${e.reset.fullName(ctx)}, ${e.init.fullName(ctx)}))" case e: DefMemory => s"cmem ${e.name} : ${e.t.toType}[${e.size}]" case e: DefSeqMemory => s"smem ${e.name} : ${e.t.toType}[${e.size}]" case e: DefMemPort[_] => s"${e.dir} mport ${e.name} = ${e.source.fullName(ctx)}[${e.index.fullName(ctx)}], ${e.clock.fullName(ctx)}" @@ -20,8 +20,9 @@ private class Emitter(circuit: Circuit) { case e: BulkConnect => s"${e.loc1.fullName(ctx)} <- ${e.loc2.fullName(ctx)}" case e: Stop => s"stop(${e.clk.fullName(ctx)}, UInt<1>(1), ${e.ret})" case e: Printf => s"""printf(${e.clk.fullName(ctx)}, UInt<1>(1), "${e.format}"${e.ids.map(_.fullName(ctx)).fold(""){_ + ", " + _}})""" + case e: DefInvalid => s"${e.arg.fullName(ctx)} is invalid" case e: DefInstance => { - val modName = moduleMap.getOrElse(e.id.name, e.id.name) + val modName = moduleMap.get(e.id.name).get s"inst ${e.name} of $modName" } @@ -32,31 +33,59 @@ private class Emitter(circuit: Circuit) { unindent() "skip" } - private def emitBody(m: Component) = { - val me = new StringBuilder + + // Map of Module FIRRTL definition to FIRRTL name, if it has been emitted already. + private val defnMap = collection.mutable.HashMap[String, String]() + // Map of Component name to FIRRTL id. + private val moduleMap = collection.mutable.HashMap[String, String]() + + /** Generates the FIRRTL module definition with a specified name. + */ + private def moduleDefn(m: Component, name: String): String = { + val body = new StringBuilder + m.id match { + case _: BlackBox => body ++= newline + s"extmodule $name : " + case _: Module => body ++= newline + s"module $name : " + } withIndent { for (p <- m.ports) - me ++= newline + emitPort(p) - me ++= newline - for (cmd <- m.commands) - me ++= newline + emit(cmd, m) - me ++= newline + body ++= newline + emitPort(p) + body ++= newline + + m.id match { + case _: BlackBox => + // TODO: BlackBoxes should be empty, but funkiness in Module() means + // it's not for now. Eventually, this should assert out. + case _: Module => for (cmd <- m.commands) { + body ++= newline + emit(cmd, m) + } + } + body ++= newline } - me + body.toString() } - private val bodyMap = collection.mutable.HashMap[StringBuilder, String]() - private val moduleMap = collection.mutable.HashMap[String, String]() - + /** Returns the FIRRTL declaration and body of a module, or nothing if it's a + * duplicate of something already emitted (on the basis of simple string + * matching). + */ private def emit(m: Component): String = { - val body = emitBody(m) - bodyMap get body match { - case Some(name) => - moduleMap(m.name) = name + // Generate the body. + val moduleName = m.id.getClass.getName.split('.').last + val defn = moduleDefn(m, moduleName) + + defnMap get defn match { + case Some(deduplicatedName) => + moduleMap(m.name) = deduplicatedName "" case None => - bodyMap(body) = m.name - newline + s"module ${m.name} : " + body + require(!(moduleMap contains m.name), + "emitting module with same name but different contents") + + moduleMap(m.name) = m.name + defnMap(defn) = m.name + + moduleDefn(m, m.name) } } diff --git a/src/main/scala/Chisel/internal/firrtl/IR.scala b/src/main/scala/Chisel/internal/firrtl/IR.scala index 5612f1af..7bb273c0 100644 --- a/src/main/scala/Chisel/internal/firrtl/IR.scala +++ b/src/main/scala/Chisel/internal/firrtl/IR.scala @@ -10,12 +10,12 @@ case class PrimOp(val name: String) { object PrimOp { val AddOp = PrimOp("add") - val AddModOp = PrimOp("addw") val SubOp = PrimOp("sub") - val SubModOp = PrimOp("subw") + val TailOp = PrimOp("tail") + val HeadOp = PrimOp("head") val TimesOp = PrimOp("mul") val DivideOp = PrimOp("div") - val ModOp = PrimOp("mod") + val RemOp = PrimOp("rem") val ShiftLeftOp = PrimOp("shl") val ShiftRightOp = PrimOp("shr") val DynamicShiftLeftOp = PrimOp("dshl") @@ -25,7 +25,6 @@ object PrimOp { 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") @@ -148,13 +147,14 @@ abstract class Definition extends Command { def name: String = id.getRef.name } case class DefPrim[T <: Data](id: T, op: PrimOp, args: Arg*) extends Definition +case class DefInvalid(arg: Arg) extends Command case class DefWire(id: Data) extends Definition -case class DefRegister(id: Data, clock: Arg, reset: Arg, init: Arg) extends Definition +case class DefReg(id: Data, clock: Arg) extends Definition +case class DefRegInit(id: Data, clock: Arg, reset: Arg, init: Arg) extends Definition case class DefMemory(id: HasId, t: Data, size: Int) extends Definition case class DefSeqMemory(id: HasId, t: Data, size: Int) extends Definition case class DefMemPort[T <: Data](id: T, source: Node, dir: MemPortDirection, index: Arg, clock: Arg) extends Definition case class DefInstance(id: Module, ports: Seq[Port]) extends Definition -case class DefPoison[T <: Data](id: T) extends Definition case class WhenBegin(pred: Arg) extends Command case class WhenEnd() extends Command case class Connect(loc: Node, exp: Arg) extends Command diff --git a/src/main/scala/Chisel/throwException.scala b/src/main/scala/Chisel/throwException.scala new file mode 100644 index 00000000..998b2cd6 --- /dev/null +++ b/src/main/scala/Chisel/throwException.scala @@ -0,0 +1,11 @@ +// See LICENSE for details + +package Chisel + +@deprecated("throwException doesn't exist in Chisel3", "3.0.0") +object throwException { + def apply(s: String, t: Throwable = null) = { + val xcpt = new Exception(s, t) + throw xcpt + } +} |
