option method of boolean Scala / Chisel

461 views Asked by At

I was trying to understand the implementation of the AsyncQueue in the RocketChip , and quite puzzled by the use of option method on Boolean data type (not Option). In the code we have a parametr class :

case class AsyncQueueParams(
  depth:  Int     = 8,
  sync:   Int     = 3,
  safe:   Boolean = true,
  narrow: Boolean = false)
{
  require (depth > 0 && isPow2(depth))
  require (sync >= 2)

  val bits = log2Ceil(depth)
  val wires = if (narrow) 1 else depth
} 

Then when the above is used:

class AsyncBundle[T <: Data](private val gen: T, val params: AsyncQueueParams = AsyncQueueParams()) extends Bundle {

  val mem   = Output(Vec(params.wires, gen))
  val ridx  = Input (UInt((params.bits+1).W))
  val widx  = Output(UInt((params.bits+1).W))
  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) // <--- Never seen use of option !!
}

Now, I can guess what was the intention here, to condition the creation of the val safe & narrow. My question is where this option is defined ? I have looked at the scala docs for Boolean. I don't see option as a member of class Boolean. Can someone explain this please ?

2

There are 2 answers

0
phongnt On BEST ANSWER

it is defined here https://github.com/chipsalliance/rocket-chip/blob/86a2f2cca699f149bcc082ef2828654a0a4e3f4b/src/main/scala/util/package.scala#L221

this pattern is what usually called "extension" or "syntax" in scala library where you can define methods on the type you don't own or don't want to couple the method with the core data structure. In older literature you might also find "XRich" or "XOps" that means the same thing.

in scala 2, the machinery to do this is via implicit class. When you have someBoolean.option(...) in your code, the compiler will search for methods in Boolean and then if not found it will try to search in all other classes that it can turn Boolean into. In this case there is implicit conversion from Boolean to BooleanToAugmentedBoolean in scope, and the compiler found the option method there.

Note that implicit class is just syntactic sugar for a normal class & an implicit converstion i.e.

implicit class BooleanToAugmentedBoolean(private val x: Boolean) extends AnyVal {
  def toInt: Int = if (x) 1 else 0
  def option[T](z: => T): Option[T] = if (x) Some(z) else None
}

is syntactic sugar for

class BooleanToAugmentedBoolean(private val x: Boolean) extends AnyVal {
  def toInt: Int = if (x) 1 else 0
  def option[T](z: => T): Option[T] = if (x) Some(z) else None
}

implicit def f(x: Boolean) = new BooleanToAugmentedBoolean(x)

0
ccheneson On

You have as import (See here)

import chisel3.util._

In the package object here, there is an extension method

  implicit class BooleanToAugmentedBoolean(private 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
  }