xref: /XiangShan/src/main/scala/xiangshan/mem/vector/VfofBuffer.scala (revision df3b4b929acc09516f17dd4b8d149c688286f5ee)
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 org.chipsalliance.cde.config.Parameters
20import chisel3._
21import chisel3.util._
22import utils._
23import utility._
24import xiangshan._
25import xiangshan.backend.rob.RobPtr
26import xiangshan.backend.Bundles._
27import xiangshan.mem._
28import xiangshan.backend.fu.vector.Bundles._
29
30
31class VfofDataBundle(implicit p: Parameters) extends VLSUBundle{
32  val uop              = new DynInst
33  val vl               = UInt(elemIdxBits.W)
34}
35
36
37class VfofBuffer(implicit p: Parameters) extends VLSUModule{
38  val io = IO(new VfofDataBuffIO())
39
40  val entries = RegInit(0.U.asTypeOf(new VfofDataBundle()))
41  val valid   = RegInit(false.B)
42
43  val entriesIsFixVl = entries.uop.vpu.lastUop && entries.uop.vpu.isVleff
44
45  //Enq
46  io.in.map(_.ready := true.B)
47  val enqIsfof = io.in.map { x =>
48    x.valid && x.bits.uop.vpu.isVleff
49  }
50
51  val enqValid = enqIsfof.reduce(_ || _)
52  val enqBits  = ParallelPriorityMux(enqIsfof, io.in.map(_.bits))
53  val enqNeedCancel = enqBits.uop.robIdx.needFlush(io.redirect)
54  val enqIsFixVl = enqBits.uop.vpu.isVleff && enqBits.uop.vpu.lastUop
55
56  XSError(entries.uop.robIdx.value =/= enqBits.uop.robIdx.value && valid && enqValid, "There should be no new fof instrction coming in\n")
57  XSError(entriesIsFixVl && valid && enqValid, "A new fof instrction enters when exiting the team\n")
58
59  when(enqValid && !enqNeedCancel) {
60    when(!valid){
61      entries.uop     := enqBits.uop
62      entries.vl      := 0.U
63      entries.vuopIdx := 0.U
64    }.elsewhen(valid && enqIsFixVl){
65      entries.uop     := enqBits.uop
66    }
67  }
68
69  //Control Signal
70  val needRedirect = entries.uop.robIdx.needFlush(io.redirect)
71
72  when(enqValid && !enqNeedCancel) {
73    valid := true.B  //Enq
74  }.elsewhen(needRedirect) {
75    valid := false.B //Redirect
76  }.elsewhen(io.uopWriteback.fire) {
77    valid := false.B //Deq
78  }
79
80  //Gather writeback information
81  val wbIsfof = io.mergeUopWriteback.map{ x => x.valid && x.bits.uop.robIdx.value === entries.uop.robIdx.value }
82
83  def getOldest(valid: Seq[Bool], bits: Seq[DynInst]): DynInst = {
84    def getOldest_recursion[T <: Data](valid: Seq[Bool], bits: Seq[DynInst]): (Seq[Bool], Seq[DynInst]) = {
85      assert(valid.length == bits.length)
86      if (valid.length == 1) {
87        (valid, bits)
88      } else if (valid.length == 2) {
89        val res = Seq.fill(2)(Wire(ValidIO(chiselTypeOf(bits(0)))))
90        for (i <- res.indices) {
91          res(i).valid := valid(i)
92          res(i).bits := bits(i)
93        }
94        val oldest = Mux(
95          !valid(1) || (bits(1).vpu.vl > bits(0).vpu.vl),
96          res(0),
97          res(1)
98        )
99        (Seq(oldest.valid), Seq(oldest.bits))
100      } else {
101        val left = getOldest_recursion(valid.take(valid.length / 2), bits.take(valid.length / 2))
102        val right = getOldest_recursion(valid.drop(valid.length / 2), bits.drop(valid.length / 2))
103        getOldest_recursion(left._1 ++ right._1, left._2 ++ right._2)
104      }
105    }
106    getOldest_recursion(valid, bits)._2.head
107  }
108
109  //Update uop vl
110  io.mergeUopWriteback.map{_.ready := true.B}
111  val wbUpdateBits  = getOldest(wbIsfof, io.mergeUopWriteback.map(_.bits.uop))
112  val wbUpdateValid = wbIsfof.reduce(_ || _) && (wbUpdateBits.vpu.vl < entries.vl || !entries.vl.orR) && valid && !needRedirect
113
114  when(wbUpdateValid) { entries.vl  := wbUpdateBits.vpu.vl }
115
116  //Deq
117  io.uopWriteback.bits               := 0.U.asTypeOf(new MemExuOutput(isVector = true))
118  io.uopWriteback.bits.uop           := entries.uop
119  io.uopWriteback.bits.data          := entries.vl
120  io.uopWriteback.bits.uop.vpu.vl    := entries.vl
121  io.uopWriteback.bits.mask.get      := Fill(VLEN, 1.U)
122  io.uopWriteback.bits.uop.vpu.vmask := Fill(VLEN, 1.U)
123  io.uopWriteback.valid              := valid && entries.uop.vpu.lastUop && entries.uop.vpu.isVleff && !needRedirect
124
125  when(io.uopWriteback.fire) { valid   := false.B }
126
127}
128