Saturday, May 6, 2017

Use of HellaQueue in Chisel, secondary constructor

This post is an expanded update to an entry in my personal "NOTES" file.  At first glance, I found the following code perplxing, therefore I decided to break it down.

class HellaQueue[T <: Data](val entries: Int)(data: => T) extends Module {
  val io = new QueueIO(data, entries)

  val fq = Module(new HellaFlowQueue(entries)(data)) <> io.enq
  io.deq <> Queue(, 1, pipe = true)

object HellaQueue {
  def apply[T <: Data](enq: DecoupledIO[T], entries: Int) = {
    val q = Module((new HellaQueue(entries)) { enq.bits }) := enq.valid // not using <> so that override is allowed := enq.bits
    enq.ready :=

What does the :< operator do in [T <: Data>]?

It is obvious (to me at least) that this is for type parameterization.  The <: operator indicates that the type supplied to the class instance must have chisel3.core.Data as an ancestor.

Why does (data: => T) do?

No suprise that (val entries: Int) is the primary constructor.  The fat arrow (=>) implies a function.  The first argument to the constructor lets you specific the number of entries.  The second argument data helps to parameterize the class.

// example usage
val xy: Data
val hq1 = (new HellaQueue(entries = 90)){xy}
// equivalent to above, without (data: => T) in the class constructor
val hq2 = (new HellaQueue[SInt](entries = 90))

Why is a class definion and a object definition of the same name?

The object is known as a companion class, consult for more info

What does the apply function do in the object?

The apply function acts as an auxillary constructor.  Allows alternative syntax for creating HellaQueue.