xref: /XiangShan/src/main/scala/xiangshan/mem/sbuffer/DatamoduleResultBuffer.scala (revision b8b991d636e3eae0d6cc2e36846166652699f0c2)
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 utility._
26import xiangshan.cache._
27import difftest._
28
29class DatamoduleResultBufferIO[T <: Data](gen: T)(implicit p: Parameters) extends XSBundle
30{
31  // val flush = Input(Bool())
32  val enq = Vec(EnsbufferWidth, Flipped(DecoupledIO(gen)))
33  val deq = Vec(EnsbufferWidth, DecoupledIO(gen))
34
35}
36
37class DatamoduleResultBuffer[T <: Data]
38(
39  gen: T,
40)(implicit p: Parameters) extends XSModule {
41
42  val genType = if (compileOptions.declaredTypeMustBeUnbound) {
43    requireIsChiselType(gen)
44    gen
45  } else {
46    if (DataMirror.internal.isSynthesizable(gen)) {
47      chiselTypeOf(gen)
48    } else {
49      gen
50    }
51  }
52
53  val io = IO(new DatamoduleResultBufferIO[T](gen))
54
55  val data = Reg(Vec(EnsbufferWidth, genType))
56  val valids = RegInit(VecInit(Seq.fill(EnsbufferWidth)(false.B)))
57  val enq_flag = RegInit(0.U(log2Up(EnsbufferWidth).W)) // head is entry 0
58  val deq_flag = RegInit(0.U(log2Up(EnsbufferWidth).W)) // tail is entry 0
59
60  val entry_allowin = Wire(Vec(EnsbufferWidth, Bool()))
61
62  (0 until EnsbufferWidth).foreach(index => {
63    io.deq(index).valid := valids(deq_flag + index.U) && (if (index == 0) 1.B else io.deq(index - 1).valid)
64    io.deq(index).bits := data(deq_flag + index.U)
65  })
66
67  (1 until EnsbufferWidth).foreach(i => {
68    assert(!(io.deq(i).valid && !io.deq(i - 1).valid))
69    assert(!(io.deq(i).ready && !io.deq(i - 1).ready))
70  })
71
72  (0 until EnsbufferWidth).foreach(
73    index => entry_allowin(index) := !valids(index) || (0 until EnsbufferWidth).map(i => io.deq(i).fire && deq_flag + i.U === index.U).reduce(_ || _)
74  )
75
76  (0 until EnsbufferWidth).foreach(
77    index => io.enq(index).ready := entry_allowin(enq_flag + index.U) && (if (index == 0) 1.B else io.enq(index - 1).ready)
78  )
79
80  (1 until EnsbufferWidth).foreach(i => {
81    assert(!(io.enq(i).ready && !io.enq(i - 1).ready))
82    assert(!(io.enq(i).valid && !io.enq(i - 1).valid))
83  })
84
85  (0 until EnsbufferWidth).foreach(index =>
86    when(io.deq(index).fire) {
87      valids(deq_flag + index.U) := 0.B
88      if (EnsbufferWidth > 1) deq_flag := deq_flag + index.U + 1.U
89    }
90  )
91
92  (0 until EnsbufferWidth).foreach(index =>
93    when(io.enq(index).fire) {
94      valids(enq_flag + index.U) := 1.B
95      data(enq_flag + index.U) := io.enq(index).bits
96      if (EnsbufferWidth > 1) enq_flag := enq_flag + index.U + 1.U
97    }
98  )
99}
100