Skip to content

Commit

Permalink
Simplify Enum API (#385)
Browse files Browse the repository at this point in the history
Get rid of some cruft exposed in #373

This also allows Bits.fromtInt(...) to be removed. Yay!

All old APIs (with some new restrictions, rocket still works fine) are preserved without deprecation in Chisel._, aside from the non-compile-time-checkable Map[] enum constructor which probably should have been deprecated during chisel2. The Map[] enums have been removed from chisel3._ without deprecation.

The new restriction is that nodeType (legacy API) may only be of UInt type with unspecified width. Note that Bits() creates a UInt, and if you can't control the enum values, it makes little sense to specify a bitwidth.
  • Loading branch information
ducky64 committed Nov 24, 2016
1 parent 08b4f68 commit edb19a0
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 47 deletions.
17 changes: 0 additions & 17 deletions chiselFrontend/src/main/scala/chisel3/core/Bits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ sealed abstract class Bits(width: Width, override val litArg: Option[LitArg])
// Arguments for: self-checking code (can't do arithmetic on bits)
// Arguments against: generates down to a FIRRTL UInt anyways

private[chisel3] def fromInt(x: BigInt, w: Int): this.type

private[chisel3] def flatten: IndexedSeq[Bits] = IndexedSeq(this)

def cloneType: this.type = cloneTypeWidth(width)
Expand Down Expand Up @@ -402,9 +400,6 @@ sealed class UInt private[core] (width: Width, lit: Option[ULit] = None)
new UInt(w).asInstanceOf[this.type]
private[chisel3] def toType = s"UInt$width"

override private[chisel3] def fromInt(value: BigInt, width: Int): this.type =
value.asUInt(width.W).asInstanceOf[this.type]

// TODO: refactor to share documentation with Num or add independent scaladoc
final def unary_- (): UInt = macro SourceInfoTransform.noArg
final def unary_-% (): UInt = macro SourceInfoTransform.noArg
Expand Down Expand Up @@ -562,9 +557,6 @@ sealed class SInt private[core] (width: Width, lit: Option[SLit] = None)
new SInt(w).asInstanceOf[this.type]
private[chisel3] def toType = s"SInt$width"

override private[chisel3] def fromInt(value: BigInt, width: Int): this.type =
value.asSInt(width.W).asInstanceOf[this.type]

final def unary_- (): SInt = macro SourceInfoTransform.noArg
final def unary_-% (): SInt = macro SourceInfoTransform.noArg

Expand Down Expand Up @@ -696,11 +688,6 @@ sealed class Bool(lit: Option[ULit] = None) extends UInt(1.W, lit) {
new Bool().asInstanceOf[this.type]
}

override private[chisel3] def fromInt(value: BigInt, width: Int): this.type = {
require((value == 0 || value == 1) && width == 1)
(value == 1).asBool.asInstanceOf[this.type]
}

// REVIEW TODO: Why does this need to exist and have different conventions
// than Bits?
final def & (that: Bool): Bool = macro SourceInfoTransform.thatArg
Expand Down Expand Up @@ -823,10 +810,6 @@ sealed class FixedPoint private (width: Width, val binaryPoint: BinaryPoint, lit
case _ => this badConnect that
}

private[chisel3] def fromInt(value: BigInt, width: Int): this.type = {
throwException(s"Don't use $this.fromInt($value, $width): Use literal constructors instead")
}

final def unary_- (): FixedPoint = macro SourceInfoTransform.noArg
final def unary_-% (): FixedPoint = macro SourceInfoTransform.noArg

Expand Down
57 changes: 56 additions & 1 deletion src/main/scala/chisel3/compatibility.scala
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,62 @@ package object Chisel { // scalastyle:ignore package.object.name
type Queue[T <: Data] = chisel3.util.Queue[T]
val Queue = chisel3.util.Queue

val Enum = chisel3.util.Enum
object Enum extends chisel3.util.Enum {
/** Returns n unique values of the specified type. Can be used with unpacking to define enums.
*
* nodeType must be of UInt type (note that Bits() creates a UInt) with unspecified width.
*
* @example {{{
* val state_on :: state_off :: Nil = Enum(UInt(), 2)
* val current_state = UInt()
* switch (current_state) {
* is (state_on) {
* ...
* }
* if (state_off) {
* ...
* }
* }
* }}}
*/
def apply[T <: Bits](nodeType: T, n: Int): List[T] = {
require(nodeType.isInstanceOf[UInt], "Only UInt supported for enums")
require(!nodeType.widthKnown, "Bit width may no longer be specified for enums")
apply(n).asInstanceOf[List[T]]
}

/** An old Enum API that returns a map of symbols to UInts.
*
* Unlike the new list-based Enum, which can be unpacked into vals that the compiler
* understands and can check, map accesses can't be compile-time checked and typos may not be
* caught until runtime.
*
* Despite being deprecated, this is not to be removed from the compatibility layer API.
* Deprecation is only to nag users to do something safer.
*/
@deprecated("Use list-based Enum", "not soon enough")
def apply[T <: Bits](nodeType: T, l: Symbol *): Map[Symbol, T] = {
require(nodeType.isInstanceOf[UInt], "Only UInt supported for enums")
require(!nodeType.widthKnown, "Bit width may no longer be specified for enums")
(l zip createValues(l.length)).toMap.asInstanceOf[Map[Symbol, T]]
}

/** An old Enum API that returns a map of symbols to UInts.
*
* Unlike the new list-based Enum, which can be unpacked into vals that the compiler
* understands and can check, map accesses can't be compile-time checked and typos may not be
* caught until runtime.
*
* Despite being deprecated, this is not to be removed from the compatibility layer API.
* Deprecation is only to nag users to do something safer.
*/
@deprecated("Use list-based Enum", "not soon enough")
def apply[T <: Bits](nodeType: T, l: List[Symbol]): Map[Symbol, T] = {
require(nodeType.isInstanceOf[UInt], "Only UInt supported for enums")
require(!nodeType.widthKnown, "Bit width may no longer be specified for enums")
(l zip createValues(l.length)).toMap.asInstanceOf[Map[Symbol, T]]
}
}

val LFSR16 = chisel3.util.LFSR16

Expand Down
41 changes: 14 additions & 27 deletions src/main/scala/chisel3/util/Enum.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ package chisel3.util

import chisel3._

object Enum {
trait Enum {
/** Returns a sequence of Bits subtypes with values from 0 until n. Helper method. */
private def createValues[T <: Bits](nodeType: T, n: Int): Seq[T] =
(0 until n).map(x => nodeType.fromInt(x, log2Up(n)))
protected def createValues(n: Int): Seq[UInt] =
(0 until n).map(_.U(log2Up(n).W))

/** Returns n unique values of the specified type. Can be used with unpacking to define enums.
/** Returns n unique UInt values, use with unpacking to specify an enumeration.
*
* @example {{{
* val state_on :: state_off :: Nil = Enum(UInt(), 2)
* val state_on :: state_off :: Nil = Enum(2)
* val current_state = UInt()
* switch (current_state) {
* is (state_on) {
Expand All @@ -26,28 +26,15 @@ object Enum {
* }
* }
* }}}
*
*/
def apply[T <: Bits](nodeType: T, n: Int): List[T] = createValues(nodeType, n).toList

/** Returns a map of the input symbols to unique values of the specified type.
*
* @example {{{
* val states = Enum(UInt(), 'on, 'off)
* val current_state = UInt()
* switch (current_state) {
* is (states('on)) {
* ...
* }
* if (states('off)) {
* ..
* }
* }
* }}}
*/
def apply[T <: Bits](nodeType: T, l: Symbol *): Map[Symbol, T] = (l zip createValues(nodeType, l.length)).toMap
def apply(n: Int): List[UInt] = createValues(n).toList
}

/** Returns a map of the input symbols to unique values of the specified type.
*/
def apply[T <: Bits](nodeType: T, l: List[Symbol]): Map[Symbol, T] = (l zip createValues(nodeType, l.length)).toMap
object Enum extends Enum {
@deprecated("use Enum(n)", "chisel3, will be removed soon")
def apply[T <: Bits](nodeType: T, n: Int): List[T] = {
require(nodeType.isInstanceOf[UInt], "Only UInt supported for enums")
require(!nodeType.widthKnown, "Bit width may no longer be specified for enums")
apply(n).asInstanceOf[List[T]]
}
}
2 changes: 1 addition & 1 deletion src/test/scala/chiselTests/Risc.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class Risc extends Module {
val code = Mem(memSize, Bits(32.W))
val pc = Reg(init=0.U(8.W))

val add_op :: imm_op :: Nil = Enum(Bits(8.W), 2)
val add_op :: imm_op :: Nil = Enum(2)

val inst = code(pc)
val op = inst(31,24)
Expand Down
2 changes: 1 addition & 1 deletion src/test/scala/chiselTests/VendingMachine.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class VendingMachine extends Module {
val valid = Output(Bool())
})
val c = 5.U(3.W)
val sIdle :: s5 :: s10 :: s15 :: sOk :: Nil = Enum(UInt(), 5)
val sIdle :: s5 :: s10 :: s15 :: sOk :: Nil = Enum(5)
val state = Reg(init = sIdle)
when (state === sIdle) {
when (io.nickel) { state := s5 }
Expand Down

0 comments on commit edb19a0

Please sign in to comment.