xref: /XiangShan/src/main/scala/xiangshan/mem/sbuffer/DatamoduleResultBuffer.scala (revision 7a2fc509e2d355879c4db3dc3f17a6ccacd3d09e)
1/***************************************************************************************
2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3* Copyright (c) 2020-2021 Peng Cheng Laboratory
4*
5* XiangShan is licensed under Mulan PSL v2.
6* You can use this software according to the terms and conditions of the Mulan PSL v2.
7* You may obtain a copy of Mulan PSL v2 at:
8*          http://license.coscl.org.cn/MulanPSL2
9*
10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13*
14* See the Mulan PSL v2 for more details.
15***************************************************************************************/
16
17package xiangshan.mem
18
19import chipsalliance.rocketchip.config.Parameters
20import chisel3.experimental.{DataMirror, requireIsChiselType}
21import chisel3._
22import chisel3.util._
23import xiangshan._
24import utils._
25import xiangshan.cache._
26import difftest._
27
28class DatamoduleResultBufferIO[T <: Data](gen: T)(implicit p: Parameters) extends XSBundle
29{
30  // val flush = Input(Bool())
31  val enq = Vec(EnsbufferWidth, Flipped(DecoupledIO(gen)))
32  val deq = Vec(EnsbufferWidth, DecoupledIO(gen))
33
34}
35
36class DatamoduleResultBuffer[T <: Data]
37(
38  gen: T,
39)(implicit p: Parameters) extends XSModule {
40
41  val genType = if (compileOptions.declaredTypeMustBeUnbound) {
42    requireIsChiselType(gen)
43    gen
44  } else {
45    if (DataMirror.internal.isSynthesizable(gen)) {
46      chiselTypeOf(gen)
47    } else {
48      gen
49    }
50  }
51
52  val io = IO(new DatamoduleResultBufferIO[T](gen))
53
54  val data = Reg(Vec(EnsbufferWidth, genType))
55  val valids = RegInit(VecInit(Seq.fill(EnsbufferWidth)(false.B)))
56  val enq_flag = RegInit(0.U(log2Up(EnsbufferWidth).W)) // head is entry 0
57  val deq_flag = RegInit(0.U(log2Up(EnsbufferWidth).W)) // tail is entry 0
58
59  val entry_allowin = Wire(Vec(EnsbufferWidth, Bool()))
60
61  (0 until EnsbufferWidth).foreach(index => {
62    io.deq(index).valid := valids(deq_flag + index.U) && (if (index == 0) 1.B else io.deq(index - 1).valid)
63    io.deq(index).bits := data(deq_flag + index.U)
64  })
65
66  (1 until EnsbufferWidth).foreach(i => {
67    assert(!(io.deq(i).valid && !io.deq(i - 1).valid))
68    assert(!(io.deq(i).ready && !io.deq(i - 1).ready))
69  })
70
71  (0 until EnsbufferWidth).foreach(
72    index => entry_allowin(index) := !valids(index) || (0 until EnsbufferWidth).map(i => io.deq(i).fire && deq_flag + i.U === index.U).reduce(_ || _)
73  )
74
75  (0 until EnsbufferWidth).foreach(
76    index => io.enq(index).ready := entry_allowin(enq_flag + index.U) && (if (index == 0) 1.B else io.enq(index - 1).ready)
77  )
78
79  (1 until EnsbufferWidth).foreach(i => {
80    assert(!(io.enq(i).ready && !io.enq(i - 1).ready))
81    assert(!(io.enq(i).valid && !io.enq(i - 1).valid))
82  })
83
84  (0 until EnsbufferWidth).foreach(index =>
85    when(io.deq(index).fire) {
86      valids(deq_flag + index.U) := 0.B
87      if (EnsbufferWidth > 1) deq_flag := deq_flag + index.U + 1.U
88    }
89  )
90
91  (0 until EnsbufferWidth).foreach(index =>
92    when(io.enq(index).fire) {
93      valids(enq_flag + index.U) := 1.B
94      data(enq_flag + index.U) := io.enq(index).bits
95      if (EnsbufferWidth > 1) enq_flag := enq_flag + index.U + 1.U
96    }
97  )
98}
99