// See LICENSE for license details. package Chisel.internal.firrtl import Chisel._ import Chisel.internal._ case class PrimOp(val name: String) { override def toString: String = name } object PrimOp { val AddOp = PrimOp("add") val SubOp = PrimOp("sub") val TailOp = PrimOp("tail") val HeadOp = PrimOp("head") val TimesOp = PrimOp("mul") val DivideOp = PrimOp("div") val RemOp = PrimOp("rem") 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 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 Arg { def fullName(ctx: Component): String = name def name: String } case class Node(id: HasId) extends Arg { override def fullName(ctx: Component): String = id.getRef.fullName(ctx) def name: String = id.getRef.name } 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, s"The literal value ${num} was elaborated with a specificed width of ${widthArg.get} bits, but at least ${minWidth} bits are required.") } } case class ILit(n: BigInt) extends Arg { def name: String = n.toString } case class ULit(n: BigInt, w: Width) extends LitArg(n, w) { def name: String = "UInt" + width + "(\"h0" + num.toString(16) + "\")" def minWidth: Int = 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: String = { val unsigned = if (n < 0) (BigInt(1) << width.get) + n else n s"asSInt(${ULit(unsigned, width).name})" } def minWidth: Int = 1 + n.bitLength } case class Ref(name: String) extends Arg case class ModuleIO(mod: Module, name: String) extends Arg { override def fullName(ctx: Component): String = if (mod eq ctx.id) name else s"${mod.getRef.name}.$name" } case class Slot(imm: Node, name: String) extends Arg { override def fullName(ctx: Component): String = if (imm.fullName(ctx).isEmpty) name else s"${imm.fullName(ctx)}.${name}" } case class Index(imm: Arg, value: Arg) extends Arg { def name: String = s"[$value]" override def fullName(ctx: Component): String = s"${imm.fullName(ctx)}[${value.fullName(ctx)}]" } 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: Boolean = false def get: Int = None.get def op(that: Width, f: (W, W) => W): Width = this override def toString: String = "" } sealed case class KnownWidth(value: Int) extends Width { require(value >= 0) def known: Boolean = true def get: Int = value def op(that: Width, f: (W, W) => W): Width = that match { case KnownWidth(x) => KnownWidth(f(value, x)) case _ => that } override def toString: String = s"<${value.toString}>" } sealed abstract class MemPortDirection(name: String) { override def toString: String = name } object MemPortDirection { object READ extends MemPortDirection("read") object WRITE extends MemPortDirection("write") object RDWR extends MemPortDirection("rdwr") object INFER extends MemPortDirection("infer") } abstract class Command abstract class Definition extends Command { def id: HasId 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 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 WhenBegin(pred: Arg) extends Command case class WhenEnd() extends Command case class Connect(loc: Node, exp: Arg) extends Command case class BulkConnect(loc1: Node, loc2: Node) extends Command case class ConnectInit(loc: Node, exp: Arg) extends Command case class Stop(clk: Arg, ret: Int) extends Command case class Component(id: Module, name: String, ports: Seq[Port], commands: Seq[Command]) extends Arg case class Port(id: Data, dir: Direction) case class Printf(clk: Arg, formatIn: String, ids: Seq[Arg]) extends Command { require(formatIn.forall(c => c.toInt > 0 && c.toInt < 128), "format strings must comprise non-null ASCII values") def format: String = { def escaped(x: Char) = { require(x.toInt >= 0) if (x == '"' || x == '\\') { s"\\${x}" } else if (x == '\n') { "\\n" } else { require(x.toInt >= 32) // TODO \xNN once FIRRTL issue #59 is resolved x } } formatIn.map(escaped _).mkString } } case class Circuit(name: String, components: Seq[Component]) { def emit: String = new Emitter(this).toString }