1df3b4b92SAnzooooo/*************************************************************************************** 2df3b4b92SAnzooooo * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3df3b4b92SAnzooooo * Copyright (c) 2020-2021 Peng Cheng Laboratory 4df3b4b92SAnzooooo * 5df3b4b92SAnzooooo * XiangShan is licensed under Mulan PSL v2. 6df3b4b92SAnzooooo * You can use this software according to the terms and conditions of the Mulan PSL v2. 7df3b4b92SAnzooooo * You may obtain a copy of Mulan PSL v2 at: 8df3b4b92SAnzooooo * http://license.coscl.org.cn/MulanPSL2 9df3b4b92SAnzooooo * 10df3b4b92SAnzooooo * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11df3b4b92SAnzooooo * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12df3b4b92SAnzooooo * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13df3b4b92SAnzooooo * 14df3b4b92SAnzooooo * See the Mulan PSL v2 for more details. 15df3b4b92SAnzooooo ***************************************************************************************/ 16df3b4b92SAnzooooo 17df3b4b92SAnzooooopackage xiangshan.mem 18df3b4b92SAnzooooo 19df3b4b92SAnzoooooimport org.chipsalliance.cde.config.Parameters 20df3b4b92SAnzoooooimport chisel3._ 21df3b4b92SAnzoooooimport chisel3.util._ 22df3b4b92SAnzoooooimport utils._ 23df3b4b92SAnzoooooimport utility._ 24df3b4b92SAnzoooooimport xiangshan._ 25df3b4b92SAnzoooooimport xiangshan.backend.rob.RobPtr 26df3b4b92SAnzoooooimport xiangshan.backend.Bundles._ 27df3b4b92SAnzoooooimport xiangshan.mem._ 28df3b4b92SAnzoooooimport xiangshan.backend.fu.vector.Bundles._ 29df3b4b92SAnzooooo 30df3b4b92SAnzooooo 31df3b4b92SAnzoooooclass VfofDataBundle(implicit p: Parameters) extends VLSUBundle{ 32df3b4b92SAnzooooo val uop = new DynInst 33df3b4b92SAnzooooo val vl = UInt(elemIdxBits.W) 34412b33bfSAnzooooo val hasException = Bool() 35df3b4b92SAnzooooo} 36df3b4b92SAnzooooo 37df3b4b92SAnzooooo 38df3b4b92SAnzoooooclass VfofBuffer(implicit p: Parameters) extends VLSUModule{ 39df3b4b92SAnzooooo val io = IO(new VfofDataBuffIO()) 40df3b4b92SAnzooooo 41df3b4b92SAnzooooo val entries = RegInit(0.U.asTypeOf(new VfofDataBundle())) 42df3b4b92SAnzooooo val valid = RegInit(false.B) 43df3b4b92SAnzooooo 44df3b4b92SAnzooooo val entriesIsFixVl = entries.uop.vpu.lastUop && entries.uop.vpu.isVleff 45df3b4b92SAnzooooo 46df3b4b92SAnzooooo //Enq 47df3b4b92SAnzooooo io.in.map(_.ready := true.B) 48df3b4b92SAnzooooo val enqIsfof = io.in.map { x => 49df3b4b92SAnzooooo x.valid && x.bits.uop.vpu.isVleff 50df3b4b92SAnzooooo } 51df3b4b92SAnzooooo 52df3b4b92SAnzooooo val enqValid = enqIsfof.reduce(_ || _) 53df3b4b92SAnzooooo val enqBits = ParallelPriorityMux(enqIsfof, io.in.map(_.bits)) 54df3b4b92SAnzooooo val enqNeedCancel = enqBits.uop.robIdx.needFlush(io.redirect) 55df3b4b92SAnzooooo val enqIsFixVl = enqBits.uop.vpu.isVleff && enqBits.uop.vpu.lastUop 56df3b4b92SAnzooooo 57412b33bfSAnzooooo XSError(entries.uop.robIdx.value =/= enqBits.uop.robIdx.value && valid && enqValid, "There should be no new fof instrction coming in!\n") 58412b33bfSAnzooooo XSError(entriesIsFixVl && valid && enqValid, "There should not new uop enqueue!\n") 59df3b4b92SAnzooooo 60df3b4b92SAnzooooo when(enqValid && !enqNeedCancel) { 61df3b4b92SAnzooooo when(!valid){ 62df3b4b92SAnzooooo entries.uop := enqBits.uop 63412b33bfSAnzooooo entries.vl := enqBits.src_vl.asTypeOf(VConfig()).vl 64412b33bfSAnzooooo entries.hasException := false.B 65df3b4b92SAnzooooo }.elsewhen(valid && enqIsFixVl){ 66df3b4b92SAnzooooo entries.uop := enqBits.uop 67df3b4b92SAnzooooo } 68df3b4b92SAnzooooo } 69df3b4b92SAnzooooo 70df3b4b92SAnzooooo //Control Signal 71df3b4b92SAnzooooo val needRedirect = entries.uop.robIdx.needFlush(io.redirect) 72df3b4b92SAnzooooo 73*640977d3SAnzooooo 74*640977d3SAnzooooo when(io.uopWriteback.fire) { 75*640977d3SAnzooooo valid := false.B //Deq 76df3b4b92SAnzooooo }.elsewhen(needRedirect) { 77df3b4b92SAnzooooo valid := false.B //Redirect 78*640977d3SAnzooooo }.elsewhen(enqValid && !enqNeedCancel) { 79*640977d3SAnzooooo valid := true.B //Enq 80df3b4b92SAnzooooo } 81df3b4b92SAnzooooo 82*640977d3SAnzooooo 83df3b4b92SAnzooooo //Gather writeback information 84412b33bfSAnzooooo val wbIsfof = io.mergeUopWriteback.map{ x => x.valid && x.bits.uop.robIdx === entries.uop.robIdx } 85df3b4b92SAnzooooo 86df3b4b92SAnzooooo def getOldest(valid: Seq[Bool], bits: Seq[DynInst]): DynInst = { 87df3b4b92SAnzooooo def getOldest_recursion[T <: Data](valid: Seq[Bool], bits: Seq[DynInst]): (Seq[Bool], Seq[DynInst]) = { 88df3b4b92SAnzooooo assert(valid.length == bits.length) 89df3b4b92SAnzooooo if (valid.length == 1) { 90df3b4b92SAnzooooo (valid, bits) 91df3b4b92SAnzooooo } else if (valid.length == 2) { 92df3b4b92SAnzooooo val res = Seq.fill(2)(Wire(ValidIO(chiselTypeOf(bits(0))))) 93df3b4b92SAnzooooo for (i <- res.indices) { 94df3b4b92SAnzooooo res(i).valid := valid(i) 95df3b4b92SAnzooooo res(i).bits := bits(i) 96df3b4b92SAnzooooo } 97412b33bfSAnzooooo val withExcep0 = bits(0).exceptionVec.asUInt.orR 98412b33bfSAnzooooo val withExcep1 = bits(1).exceptionVec.asUInt.orR 992d1596c2SAnzooooo XSError(this.valid && withExcep0 && withExcep1 && valid(0) && valid(1), "Writeback to multiple Uop with exceptions at the same time!\n") 100df3b4b92SAnzooooo val oldest = Mux( 101412b33bfSAnzooooo valid(0) && valid(1), 102412b33bfSAnzooooo Mux((bits(1).vpu.vl > bits(0).vpu.vl || withExcep0) && !withExcep1, res(0), res(1)), 103412b33bfSAnzooooo Mux(valid(0) && !valid(1), res(0), res(1)) 104df3b4b92SAnzooooo ) 105df3b4b92SAnzooooo (Seq(oldest.valid), Seq(oldest.bits)) 106df3b4b92SAnzooooo } else { 107df3b4b92SAnzooooo val left = getOldest_recursion(valid.take(valid.length / 2), bits.take(valid.length / 2)) 108df3b4b92SAnzooooo val right = getOldest_recursion(valid.drop(valid.length / 2), bits.drop(valid.length / 2)) 109df3b4b92SAnzooooo getOldest_recursion(left._1 ++ right._1, left._2 ++ right._2) 110df3b4b92SAnzooooo } 111df3b4b92SAnzooooo } 112df3b4b92SAnzooooo getOldest_recursion(valid, bits)._2.head 113df3b4b92SAnzooooo } 114df3b4b92SAnzooooo 115df3b4b92SAnzooooo //Update uop vl 116df3b4b92SAnzooooo io.mergeUopWriteback.map{_.ready := true.B} 117412b33bfSAnzooooo val wbBits = getOldest(wbIsfof, io.mergeUopWriteback.map(_.bits.uop)) 118412b33bfSAnzooooo val wbValid = wbIsfof.reduce(_ || _) 119412b33bfSAnzooooo val wbHasException = wbBits.exceptionVec.asUInt.orR 120412b33bfSAnzooooo val wbUpdateValid = wbValid && (wbBits.vpu.vl < entries.vl || wbHasException) && valid && !needRedirect && !entries.hasException 121412b33bfSAnzooooo 122412b33bfSAnzooooo XSError(wbValid && wbHasException && valid && entries.hasException, "The same instruction triggers an exception multiple times!\n") 123df3b4b92SAnzooooo 12441c5202dSAnzooooo when(wbUpdateValid) { 125412b33bfSAnzooooo entries.vl := wbBits.vpu.vl 126412b33bfSAnzooooo entries.hasException := wbHasException 12741c5202dSAnzooooo } 128df3b4b92SAnzooooo 129df3b4b92SAnzooooo //Deq 130df3b4b92SAnzooooo io.uopWriteback.bits := 0.U.asTypeOf(new MemExuOutput(isVector = true)) 131df3b4b92SAnzooooo io.uopWriteback.bits.uop := entries.uop 132412b33bfSAnzooooo io.uopWriteback.bits.uop.exceptionVec := 0.U.asTypeOf(ExceptionVec()) 133df3b4b92SAnzooooo io.uopWriteback.bits.data := entries.vl 134df3b4b92SAnzooooo io.uopWriteback.bits.uop.vpu.vl := entries.vl 135df3b4b92SAnzooooo io.uopWriteback.bits.mask.get := Fill(VLEN, 1.U) 136df3b4b92SAnzooooo io.uopWriteback.bits.uop.vpu.vmask := Fill(VLEN, 1.U) 137df3b4b92SAnzooooo io.uopWriteback.valid := valid && entries.uop.vpu.lastUop && entries.uop.vpu.isVleff && !needRedirect 138df3b4b92SAnzooooo 139df3b4b92SAnzooooo 140df3b4b92SAnzooooo} 141