[CodeStudy] Some Chisel details in the project RocketChip

Published: by Creative Commons Licence (Last updated: )

implicit classes

rocketchip/src/main/scala/util/package.scala

holdUnless

implicit class DataToAugmentedData[T <: Data](val x: T) extends AnyVal {
    def holdUnless(enable: Bool): T = Mux(enable, x, RegEnable(x, enable))
}

When enable is true, then current value is x and at the same time, the value in the register will change to x as well.

Hence, when enable is false, then the current value will be the value in the register x.

BooleanToAugmentedBoolean

implicit class BooleanToAugmentedBoolean(val x: Boolean) extends AnyVal {
    def toInt: Int = if (x) 1 else 0

    // this one's snagged from scalaz
    def option[T](z: => T): Option[T] = if (x) Some(z) else None
}

option could used to new some conditional ports.

Example: rocketchip/src/main/scala/util/AsyncQueue.scala

class AsyncBundle[T <: Data](private val gen: T, val params: AsyncQueueParams = AsyncQueueParams()) extends Bundle {
  // Data-path synchronization
  ...
  val index = params.narrow.option(Input(UInt(params.bits.W)))

  // Signals used to self-stabilize a safe AsyncQueue
  val safe = params.safe.option(new AsyncBundleSafety)
}

Gray Counter

rocketchip/src/main/scala/util/AsyncQueue.scala

object GrayCounter {
  def apply(bits: Int, increment: Bool = true.B, clear: Bool = false.B, name: String = "binary"): UInt = {
    val incremented = Wire(UInt(bits.W))
    val binary = RegNext(next=incremented, init=0.U).suggestName(name)
    incremented := Mux(clear, 0.U, binary + increment.asUInt())
    incremented ^ (incremented >> 1)
  }
}

Although it outputs gray codes, but need more resources than common codes here.