All Downloads are FREE. Search and download functionalities are using the official Maven repository.

examples.heappriorityqueue.PriorityQueue.scala Maven / Gradle / Ivy

package examples.heappriorityqueue

import chisel3._
import chisel3.util._

import examples.heappriorityqueue.Interfaces._
import examples.heappriorityqueue.modules.{QueueControl, linearSearchMem}

case class PriorityQueueParameters(size: Int, order: Int, superCycleWidth: Int, cycleWidth: Int, referenceIdWidth: Int)

/**
  * Component implementing a priority queue, where the minimum value gets to the head of the queue
  *  - The sorting is based on heap sort
  *  - inserted priorities are made up of 3 fields:
  *    - cyclic priority which is most important
  *    - normal priority which decides in the case of equal cyclic priorities
  *    - a user generated reference ID given at insertion which is used to remove elements from the queue
  *  - the component needs to be provided with the following:
  *    - a synchronous memory of appropriate size
  *      - the memory has to be initialized to all 1s
  *      - thus the reference ID with all 1s is reserved for empty cells
  *    - a component which is able to search through the reference ID fields and return the index where a given reference ID is present
  *      - the queue waits until the search result is given
  *  - the head element is kept locally in a FF for symmetry and access speed reasons
  *  - the head element is furthermore presented at a dedicated port
  *
  * @param size    the maximum size of the heap
  * @param order the number of children per node in the tree. Must be power of 2
  * @param nWid    width of the normal priority value
  * @param cWid    width of the cyclic priority value
  * @param rWid    width of the reference ID tags
  */
class PriorityQueue(size: Int, order: Int, superCycleRes: Int, cyclesPerSuperCycle: Int, exposeState: Boolean = false) extends Module {
  require(isPow2(order), "The number of children per node needs to be a power of 2!")

  val superCycleWidth = superCycleRes
  val cycleWidth = log2Ceil(cyclesPerSuperCycle)
  val referenceIdWidth = log2Ceil(size+1)
  implicit val parameters = PriorityQueueParameters(size, order, superCycleWidth, cycleWidth, referenceIdWidth)

  val io = IO(new Bundle {
    // Interface for signaling head element to user.
    // I.e. the element with the lowest priority
    val head = new Bundle {
      val valid = Output(Bool())
      val none = Output(Bool())
      val prio = Output(new Event)
      val refID = Output(UInt(referenceIdWidth.W))
    }

    // Interface for element insertion/removal
    // Timing:
    // User must maintain input asserted until done is asserted.
    // User must deassert input when done is asserted (unless a new cmd is made).
    // User must ensure that reference ID tags are unique.
    val cmd = new Bundle {
      // inputs
      val valid = Input(Bool())
      val op = Input(Bool()) // 0=Remove, 1=Insert
      val prio = Input(new Event)
      val refID = Input(UInt(referenceIdWidth.W))
      // outputs
      val done = Output(Bool())
      val result = Output(Bool()) // 0=Success, 1=Failure
      val rm_prio = Output(new Event)
    }

    val state = if (exposeState) Some(Output(UInt())) else None
  })

  val mem = Module(new linearSearchMem(size - 1))
  val queue = Module(new QueueControl)

  mem.srch <> queue.io.srch
  mem.rd <> queue.io.rdPort
  mem.wr <> queue.io.wrPort
  io.head <> queue.io.head
  io.cmd <> queue.io.cmd

  io.cmd.done := mem.srch.done && queue.io.cmd.done

  if (exposeState) io.state.get := queue.io.state
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy