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 val hasException = Bool() 35} 36 37 38class VfofBuffer(implicit p: Parameters) extends VLSUModule{ 39 val io = IO(new VfofDataBuffIO()) 40 41 val entries = RegInit(0.U.asTypeOf(new VfofDataBundle())) 42 val valid = RegInit(false.B) 43 44 val entriesIsFixVl = entries.uop.vpu.lastUop && entries.uop.vpu.isVleff 45 46 //Enq 47 io.in.map(_.ready := true.B) 48 val enqIsfof = io.in.map { x => 49 x.valid && x.bits.uop.vpu.isVleff 50 } 51 52 val enqValid = enqIsfof.reduce(_ || _) 53 val enqBits = ParallelPriorityMux(enqIsfof, io.in.map(_.bits)) 54 val enqNeedCancel = enqBits.uop.robIdx.needFlush(io.redirect) 55 val enqIsFixVl = enqBits.uop.vpu.isVleff && enqBits.uop.vpu.lastUop 56 57 XSError(entries.uop.robIdx.value =/= enqBits.uop.robIdx.value && valid && enqValid, "There should be no new fof instrction coming in!\n") 58 XSError(entriesIsFixVl && valid && enqValid, "There should not new uop enqueue!\n") 59 60 when(enqValid && !enqNeedCancel) { 61 when(!valid){ 62 entries.uop := enqBits.uop 63 entries.vl := enqBits.src_vl.asTypeOf(VConfig()).vl 64 entries.hasException := false.B 65 }.elsewhen(valid && enqIsFixVl){ 66 entries.uop := enqBits.uop 67 } 68 } 69 70 //Control Signal 71 val needRedirect = entries.uop.robIdx.needFlush(io.redirect) 72 73 74 when(io.uopWriteback.fire) { 75 valid := false.B //Deq 76 }.elsewhen(needRedirect) { 77 valid := false.B //Redirect 78 }.elsewhen(enqValid && !enqNeedCancel) { 79 valid := true.B //Enq 80 } 81 82 83 //Gather writeback information 84 val wbIsfof = io.mergeUopWriteback.map{ x => x.valid && x.bits.uop.robIdx === entries.uop.robIdx } 85 86 def getOldest(valid: Seq[Bool], bits: Seq[DynInst]): DynInst = { 87 def getOldest_recursion[T <: Data](valid: Seq[Bool], bits: Seq[DynInst]): (Seq[Bool], Seq[DynInst]) = { 88 assert(valid.length == bits.length) 89 if (valid.length == 1) { 90 (valid, bits) 91 } else if (valid.length == 2) { 92 val res = Seq.fill(2)(Wire(ValidIO(chiselTypeOf(bits(0))))) 93 for (i <- res.indices) { 94 res(i).valid := valid(i) 95 res(i).bits := bits(i) 96 } 97 val withExcep0 = bits(0).exceptionVec.asUInt.orR 98 val withExcep1 = bits(1).exceptionVec.asUInt.orR 99 XSError(this.valid && withExcep0 && withExcep1 && valid(0) && valid(1), "Writeback to multiple Uop with exceptions at the same time!\n") 100 val oldest = Mux( 101 valid(0) && valid(1), 102 Mux((bits(1).vpu.vl > bits(0).vpu.vl || withExcep0) && !withExcep1, res(0), res(1)), 103 Mux(valid(0) && !valid(1), res(0), res(1)) 104 ) 105 (Seq(oldest.valid), Seq(oldest.bits)) 106 } else { 107 val left = getOldest_recursion(valid.take(valid.length / 2), bits.take(valid.length / 2)) 108 val right = getOldest_recursion(valid.drop(valid.length / 2), bits.drop(valid.length / 2)) 109 getOldest_recursion(left._1 ++ right._1, left._2 ++ right._2) 110 } 111 } 112 getOldest_recursion(valid, bits)._2.head 113 } 114 115 //Update uop vl 116 io.mergeUopWriteback.map{_.ready := true.B} 117 val wbBits = getOldest(wbIsfof, io.mergeUopWriteback.map(_.bits.uop)) 118 val wbValid = wbIsfof.reduce(_ || _) 119 val wbHasException = wbBits.exceptionVec.asUInt.orR 120 val wbUpdateValid = wbValid && (wbBits.vpu.vl < entries.vl || wbHasException) && valid && !needRedirect && !entries.hasException 121 122 XSError(wbValid && wbHasException && valid && entries.hasException, "The same instruction triggers an exception multiple times!\n") 123 124 when(wbUpdateValid) { 125 entries.vl := wbBits.vpu.vl 126 entries.hasException := wbHasException 127 } 128 129 //Deq 130 io.uopWriteback.bits := 0.U.asTypeOf(new MemExuOutput(isVector = true)) 131 io.uopWriteback.bits.uop := entries.uop 132 io.uopWriteback.bits.uop.exceptionVec := 0.U.asTypeOf(ExceptionVec()) 133 io.uopWriteback.bits.data := entries.vl 134 io.uopWriteback.bits.uop.vpu.vl := entries.vl 135 io.uopWriteback.bits.mask.get := Fill(VLEN, 1.U) 136 io.uopWriteback.bits.uop.vpu.vmask := Fill(VLEN, 1.U) 137 io.uopWriteback.valid := valid && entries.uop.vpu.lastUop && entries.uop.vpu.isVleff && !needRedirect 138 139 140} 141