Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[rtl] complete stdlib Queue and add "almost" ports #823

Merged
merged 1 commit into from
Nov 1, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 85 additions & 54 deletions stdlib/src/Queue.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import org.chipsalliance.dwbb.interface.DW_fifo_s1_sf.{Interface => DwbbFifoInte
import chisel3.ltl.AssertProperty
import chisel3.util.{Decoupled, DecoupledIO, DeqIO, EnqIO, ReadyValidIO}

class QueueIO[T <: Data](private val gen: T) extends Bundle {
class QueueIO[T <: Data](private val gen: T, entries: Int) extends Bundle {
val enq = Flipped(EnqIO(gen))
val deq = Flipped(DeqIO(gen))

val empty = Output(Bool())
val full = Output(Bool())
val empty = Output(Bool())
val full = Output(Bool())
val almostEmpty = if (entries >= 2) Some(Output(Bool())) else None
val almostFull = if (entries >= 2) Some(Output(Bool())) else None
}

object Queue {
Expand All @@ -23,79 +25,108 @@ object Queue {
flow: Boolean = false,
resetMem: Boolean = false
): DecoupledIO[T] = {

val io = this.io(chiselTypeOf(enq.bits), entries, pipe, flow, resetMem)
io.enq <> enq

io.deq
}

def io[T <: Data](
gen: T,
entries: Int = 2,
pipe: Boolean = false,
flow: Boolean = false,
resetMem: Boolean = false
gen: T,
entries: Int = 2,
pipe: Boolean = false,
flow: Boolean = false,
resetMem: Boolean = false,
almostEmptyLevel: Int = 1,
almostFullLevel: Int = 1
): QueueIO[T] = {
require(gen.getWidth <= 2048, "Data width must be less than 2048")
require(entries <= 1024, "Entries must be less than 1024")
require(
Range.inclusive(1, 2048).contains(gen.getWidth),
"Data width must be between 1 and 2048"
)
require(
Range.inclusive(1, 1024).contains(entries),
"Entries must be between 1 and 1024"
)

val clock = Module.clock
val reset = Module.reset
val io = Wire(new QueueIO(gen, entries))

val io = Wire(new QueueIO(gen))
if (entries == 1) {
val data = if (resetMem) RegInit(0.U.asTypeOf(gen)) else Reg(gen)
val empty = RegInit(true.B)
val full = !empty

if (entries < 2) {
val queue = Module(new chisel3.util.Queue(gen, entries, pipe, flow))
queue.io.enq <> io.enq
queue.io.deq <> io.deq
io.empty := queue.io.count === 0.U
io.full := queue.io.count === entries.U
val push = io.enq.fire && (if (flow) !(empty && io.deq.ready) else true.B)
io.enq.ready := empty || (if (pipe) io.deq.ready else false.B)
data := Mux(push, io.enq.bits, data)

return io
}
val pop = io.deq.ready && full
io.deq.valid := full || (if (flow) io.enq.valid else false.B)
io.deq.bits := (if (flow) Mux(empty, io.enq.bits, data) else data)

// TODO: use sync reset for now and wait for t1 to migrate to FixedIOModule
// require(reset.typeName == "Bool" || reset.typeName == "AsyncReset")
val useAsyncReset = reset.typeName == "AsyncReset"

val fifo = Instantiate(
new DwbbFifo(
new DwbbFifoParameter(
width = gen.getWidth,
depth = entries,
errMode = "unlatched",
rstMode = (useAsyncReset, resetMem) match {
case (false, false) => "sync_wo_mem"
case (false, true) => "sync_with_mem"
case (true, false) => "async_wo_mem"
case (true, true) => "async_with_mem"
}
empty := Mux(push =/= pop, pop, empty)

io.empty := empty
io.full := full
} else {
require(
Range.inclusive(1, entries - 1).contains(almostEmptyLevel),
"almost empty level must be between 1 and entries-1"
)
require(
Range.inclusive(1, entries - 1).contains(almostFullLevel),
"almost full level must be between 1 and entries-1"
)

val clock = Module.clock
val reset = Module.reset

// TODO: use sync reset for now and wait for t1 to migrate to FixedIOModule
// require(reset.typeName == "Bool" || reset.typeName == "AsyncReset")
val useAsyncReset = reset.typeName == "AsyncReset"

val fifo = Instantiate(
new DwbbFifo(
new DwbbFifoParameter(
width = gen.getWidth,
depth = entries,
aeLevel = almostEmptyLevel,
afLevel = almostFullLevel,
errMode = "unlatched",
rstMode = (useAsyncReset, resetMem) match {
case (false, false) => "sync_wo_mem"
case (false, true) => "sync_with_mem"
case (true, false) => "async_wo_mem"
case (true, true) => "async_with_mem"
}
)
)
)
)

val dataIn = io.enq.bits.asUInt
val dataOut = fifo.io.data_out.asTypeOf(io.deq.bits)
val dataIn = io.enq.bits.asUInt
val dataOut = fifo.io.data_out.asTypeOf(io.deq.bits)

fifo.io.clk := clock
fifo.io.rst_n := ~(reset.asBool)
fifo.io.clk := clock
fifo.io.rst_n := ~(reset.asBool)

fifo.io.diag_n := ~(false.B)
fifo.io.diag_n := ~(false.B)

io.enq.ready := !fifo.io.full || (if (pipe) io.deq.ready else false.B)
fifo.io.push_req_n := ~(io.enq.fire && (if (flow) !(fifo.io.empty && io.deq.ready) else true.B))
fifo.io.data_in := dataIn
io.enq.ready := !fifo.io.full || (if (pipe) io.deq.ready else false.B)
fifo.io.push_req_n := ~(io.enq.fire && (if (flow) !(fifo.io.empty && io.deq.ready) else true.B))
fifo.io.data_in := dataIn

io.deq.valid := !fifo.io.empty || (if (flow) io.enq.valid else false.B)
fifo.io.pop_req_n := ~(io.deq.ready && !fifo.io.empty)
io.deq.bits := (if (flow) Mux(fifo.io.empty, io.enq.bits, dataOut) else dataOut)
io.deq.valid := !fifo.io.empty || (if (flow) io.enq.valid else false.B)
fifo.io.pop_req_n := ~(io.deq.ready && !fifo.io.empty)
io.deq.bits := (if (flow) Mux(fifo.io.empty, io.enq.bits, dataOut) else dataOut)

io.empty := fifo.io.empty
io.full := fifo.io.full
io.empty := fifo.io.empty
io.full := fifo.io.full
io.almostEmpty.get := fifo.io.almost_empty
io.almostFull.get := fifo.io.almost_full

// There should be no error since we guarantee to push/pop items only when the fifo is neither empty nor full.
AssertProperty(!fifo.io.error)
// There should be no error since we guarantee to push/pop items only when the fifo is neither empty nor full.
AssertProperty(!fifo.io.error)
}

io
}
Expand Down