xref: /XiangShan/src/main/scala/xiangshan/frontend/icache/FIFO.scala (revision 415fcbe20489a5e4808fcba63c48175ae1c48e28)
1/***************************************************************************************
2* Copyright (c) 2024 Beijing Institute of Open Source Chip (BOSC)
3* Copyright (c) 2020-2024 Institute of Computing Technology, Chinese Academy of Sciences
4* Copyright (c) 2020-2021 Peng Cheng Laboratory
5*
6* XiangShan is licensed under Mulan PSL v2.
7* You can use this software according to the terms and conditions of the Mulan PSL v2.
8* You may obtain a copy of Mulan PSL v2 at:
9*          http://license.coscl.org.cn/MulanPSL2
10*
11* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
12* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
13* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
14*
15* See the Mulan PSL v2 for more details.
16***************************************************************************************/
17
18package xiangshan.frontend.icache
19
20import chisel3._
21import chisel3.util._
22import utility._
23
24class FIFORegIO[T <: Data](gen: T, hasFlush: Boolean = false) extends Bundle {
25  val enq:   DecoupledIO[T] = Flipped(DecoupledIO(gen))
26  val deq:   DecoupledIO[T] = DecoupledIO(gen)
27  val flush: Option[Bool]   = Option.when(hasFlush)(Input(Bool()))
28}
29
30class FIFOReg[T <: Data](
31    val gen:      T,
32    val entries:  Int,
33    val pipe:     Boolean = false,
34    val hasFlush: Boolean = false
35) extends Module() {
36  require(entries > 0, "Queue must have non-negative number of entries")
37
38  val io: FIFORegIO[T] = IO(new FIFORegIO(gen, hasFlush))
39  private val flush = io.flush.getOrElse(false.B)
40
41  private class FIFOPtr extends CircularQueuePtr[FIFOPtr](entries)
42  private object FIFOPtr {
43    def apply(f: Bool, v: UInt): FIFOPtr = {
44      val ptr = Wire(new FIFOPtr)
45      ptr.flag  := f
46      ptr.value := v
47      ptr
48    }
49  }
50
51  private val regFiles = RegInit(VecInit(Seq.fill(entries)(0.U.asTypeOf(gen.cloneType))))
52  private val enq_ptr  = RegInit(FIFOPtr(false.B, 0.U))
53  private val deq_ptr  = RegInit(FIFOPtr(false.B, 0.U))
54
55  private val empty = enq_ptr === deq_ptr
56  private val full  = (enq_ptr.value === deq_ptr.value) && (enq_ptr.flag ^ deq_ptr.flag)
57
58  when(io.enq.fire) {
59    enq_ptr := enq_ptr + 1.U
60  }
61  when(io.deq.fire) {
62    deq_ptr := deq_ptr + 1.U
63  }
64  when(flush) {
65    enq_ptr.value := 0.U
66    enq_ptr.flag  := false.B
67    deq_ptr.value := 0.U
68    deq_ptr.flag  := false.B
69  }
70
71  when(io.enq.fire) {
72    regFiles(enq_ptr.value) := io.enq.bits
73  }
74  io.deq.bits := regFiles(deq_ptr.value)
75
76  io.deq.valid := !empty
77  io.enq.ready := !full
78  if (pipe) {
79    when(io.deq.ready)(io.enq.ready := true.B)
80  }
81}
82