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.backend.decode 18 19import chipsalliance.rocketchip.config.Parameters 20import chisel3._ 21import chisel3.util._ 22import freechips.rocketchip.rocket.Instructions 23import freechips.rocketchip.util.uintToBitPat 24import utils._ 25import utility._ 26import xiangshan.ExceptionNO.illegalInstr 27import xiangshan._ 28import xiangshan.backend.fu.fpu.FPU 29import freechips.rocketchip.rocket.Instructions._ 30import yunsuan.VppuType 31import scala.collection.Seq 32 33class DecodeUnitCompIO(implicit p: Parameters) extends XSBundle { 34 val enq = new Bundle { val ctrl_flow = Input(new CtrlFlow) } 35 val vconfig = Input(new VConfig) 36 val isComplex = Input(Vec(DecodeWidth - 1, Bool())) 37 val validFromIBuf = Input(Vec(DecodeWidth, Bool())) 38 val readyFromRename = Input(Vec(RenameWidth, Bool())) 39 val deq = new Bundle { 40 val cf_ctrl = Output(Vec(RenameWidth, new CfCtrl)) 41 val isVset = Output(Bool()) 42 val readyToIBuf = Output(Vec(DecodeWidth, Bool())) 43 val validToRename = Output(Vec(RenameWidth, Bool())) 44 val complexNum = Output(UInt(3.W)) 45 } 46 val csrCtrl = Input(new CustomCSRCtrlIO) 47} 48 49class DecodeUnitComp(maxNumOfUop : Int)(implicit p : Parameters) extends XSModule with DecodeUnitConstants { 50 val io = IO(new DecodeUnitCompIO) 51 //input bits 52 val ctrl_flow = Wire(new CtrlFlow) 53 ctrl_flow := io.enq.ctrl_flow 54 //output bits 55 val cf_ctrl = Wire(Vec(RenameWidth, new CfCtrl())) 56 val validToRename = Wire(Vec(RenameWidth, Bool())) 57 val readyToIBuf = Wire(Vec(DecodeWidth, Bool())) 58 val complexNum = Wire(UInt(3.W)) 59 60 //output of DecodeUnit 61 val cf_ctrl_u = Wire(new CfCtrl) 62 val isVset_u = Wire(Bool()) 63 val isComplex_u = Wire(Bool()) 64 65 //pre decode 66 val simple = Module(new DecodeUnit) 67 simple.io.enq.ctrl_flow := ctrl_flow 68 simple.io.vconfig := io.vconfig 69 simple.io.csrCtrl := io.csrCtrl 70 cf_ctrl_u := simple.io.deq.cf_ctrl 71 isVset_u := simple.io.deq.isVset 72 isComplex_u := simple.io.deq.isComplex 73 74 //Type of uop Div 75 val typeOfDiv = cf_ctrl_u.ctrl.uopDivType 76 77 //LMUL 78 val lmul = MuxLookup(simple.io.vconfig.vtype.vlmul, 1.U, Array( 79 "b001".U -> 2.U, 80 "b010".U -> 4.U, 81 "b011".U -> 8.U 82 )) 83 //number of uop 84 val numOfUop = MuxLookup(typeOfDiv, 1.U, Array( 85 UopDivType.VEC_MV -> 2.U, 86 UopDivType.DIR -> 2.U, 87 UopDivType.VEC_LMUL -> lmul, 88 UopDivType.VEC_MV_LMUL -> (lmul + 1.U) 89 )) 90 91 //uop div up to maxNumOfUop 92 val csBundle = Wire(Vec(maxNumOfUop, new CfCtrl)) 93 csBundle.map { case dst => dst := cf_ctrl_u } 94 95 switch(typeOfDiv) { 96 is(UopDivType.DIR) { 97 when(isVset_u) { 98 csBundle(0).ctrl.uopIdx.flags := false.B 99 csBundle(0).ctrl.uopIdx.value := 0.U 100 csBundle(0).ctrl.flushPipe := false.B 101 csBundle(0).ctrl.fuOpType := ALUOpType.vsetExchange(cf_ctrl_u.ctrl.fuOpType) 102 csBundle(1).ctrl.ldest := 32.U 103 csBundle(1).ctrl.flushPipe := FuType.isIntExu(cf_ctrl_u.ctrl.fuType) && ALUOpType.isVsetvli(cf_ctrl_u.ctrl.fuOpType) && cf_ctrl_u.ctrl.lsrc(0).orR 104 } 105 } 106 is(UopDivType.VEC_LMUL) { 107 for (i <- 0 until 8) { 108 csBundle(i).ctrl.srcType(3) := 0.U 109 csBundle(i).ctrl.lsrc(0) := ctrl_flow.instr(19, 15) + i.U 110 csBundle(i).ctrl.lsrc(1) := ctrl_flow.instr(24, 20) + i.U 111 csBundle(i).ctrl.ldest := ctrl_flow.instr(11, 7) + i.U 112 csBundle(i).ctrl.uopIdx.flags := false.B 113 csBundle(i).ctrl.uopIdx.value := i.U 114 } 115 csBundle(numOfUop - 1.U).ctrl.uopIdx.flags := true.B 116 } 117 is(UopDivType.VEC_MV) { 118 /* 119 FMV.D.X 120 */ 121 csBundle(0).ctrl.srcType(0) := SrcType.reg 122 csBundle(0).ctrl.srcType(1) := SrcType.imm 123 csBundle(0).ctrl.lsrc(1) := 0.U 124 csBundle(0).ctrl.ldest := 33.U 125 csBundle(0).ctrl.uopIdx.flags := false.B 126 csBundle(0).ctrl.uopIdx.value := 0.U 127 csBundle(0).ctrl.fuType := FuType.i2f 128 csBundle(0).ctrl.rfWen := false.B 129 csBundle(0).ctrl.fpWen := true.B 130 csBundle(0).ctrl.vecWen := false.B 131 csBundle(0).ctrl.fpu.isAddSub := false.B 132 csBundle(0).ctrl.fpu.typeTagIn := FPU.D 133 csBundle(0).ctrl.fpu.typeTagOut := FPU.D 134 csBundle(0).ctrl.fpu.fromInt := true.B 135 csBundle(0).ctrl.fpu.wflags := false.B 136 csBundle(0).ctrl.fpu.fpWen := true.B 137 csBundle(0).ctrl.fpu.div := false.B 138 csBundle(0).ctrl.fpu.sqrt := false.B 139 csBundle(0).ctrl.fpu.fcvt := false.B 140 /* 141 vfmv.s.f 142 */ 143 csBundle(1).ctrl.srcType(0) := SrcType.fp 144 csBundle(1).ctrl.srcType(1) := SrcType.vp 145 csBundle(1).ctrl.srcType(2) := SrcType.vp 146 csBundle(1).ctrl.lsrc(0) := 33.U 147 csBundle(1).ctrl.lsrc(1) := 0.U 148 csBundle(1).ctrl.lsrc(2) := ctrl_flow.instr(11, 7) 149 csBundle(1).ctrl.ldest := ctrl_flow.instr(11, 7) 150 csBundle(1).ctrl.uopIdx.flags := true.B 151 csBundle(1).ctrl.uopIdx.value := 1.U 152 csBundle(1).ctrl.fuType := FuType.vppu 153 csBundle(1).ctrl.fuOpType := VppuType.f2s 154 csBundle(1).ctrl.rfWen := false.B 155 csBundle(1).ctrl.fpWen := false.B 156 csBundle(1).ctrl.vecWen := true.B 157 } 158 is(UopDivType.VEC_MV_LMUL) { 159 /* 160 FMV.D.X 161 */ 162 csBundle(0).ctrl.srcType(0) := SrcType.reg 163 csBundle(0).ctrl.srcType(1) := SrcType.imm 164 csBundle(0).ctrl.lsrc(1) := 0.U 165 csBundle(0).ctrl.ldest := 33.U 166 csBundle(0).ctrl.uopIdx.flags := false.B 167 csBundle(0).ctrl.uopIdx.value := 0.U 168 csBundle(0).ctrl.fuType := FuType.i2f 169 csBundle(0).ctrl.rfWen := false.B 170 csBundle(0).ctrl.fpWen := false.B 171 csBundle(0).ctrl.vecWen := true.B 172 csBundle(0).ctrl.fpu.isAddSub := false.B 173 csBundle(0).ctrl.fpu.typeTagIn := FPU.D 174 csBundle(0).ctrl.fpu.typeTagOut := FPU.D 175 csBundle(0).ctrl.fpu.fromInt := true.B 176 csBundle(0).ctrl.fpu.wflags := false.B 177 csBundle(0).ctrl.fpu.fpWen := false.B 178 csBundle(0).ctrl.fpu.div := false.B 179 csBundle(0).ctrl.fpu.sqrt := false.B 180 csBundle(0).ctrl.fpu.fcvt := false.B 181 /* 182 LMUL 183 */ 184 for (i <- 0 until 8) { 185 csBundle(i + 1).ctrl.srcType(0) := SrcType.vp 186 csBundle(i + 1).ctrl.srcType(3) := 0.U 187 csBundle(i + 1).ctrl.lsrc(0) := 33.U 188 csBundle(i + 1).ctrl.lsrc(1) := ctrl_flow.instr(24, 20) + i.U 189 csBundle(i + 1).ctrl.ldest := ctrl_flow.instr(11, 7) + i.U 190 csBundle(i + 1).ctrl.uopIdx.flags := false.B 191 csBundle(i + 1).ctrl.uopIdx.value := (i + 1).U 192 } 193 csBundle(numOfUop - 1.U).ctrl.uopIdx.flags := true.B 194 } 195 } 196 197 //uops dispatch 198 val normal :: ext :: Nil = Enum(2) 199 val stateReg = RegInit(normal) 200 val uopRes = RegInit(0.U) 201 202 //readyFromRename Counter 203 val readyCounter = PriorityMuxDefault(io.readyFromRename.map(x => !x).zip((0 to (RenameWidth - 1)).map(_.U)), RenameWidth.U) 204 205 switch(stateReg) { 206 is(normal) { 207 when(!io.validFromIBuf(0)) { 208 stateReg := normal 209 uopRes := 0.U 210 }.elsewhen((numOfUop > readyCounter) && (readyCounter =/= 0.U)){ 211 stateReg := ext 212 uopRes := numOfUop - readyCounter 213 }.otherwise { 214 stateReg := normal 215 uopRes := 0.U 216 } 217 } 218 is(ext) { 219 when(!io.validFromIBuf(0)) { 220 stateReg := normal 221 uopRes := 0.U 222 }.elsewhen(uopRes > readyCounter) { 223 stateReg := ext 224 uopRes := uopRes - readyCounter 225 }.otherwise { 226 stateReg := normal 227 uopRes := 0.U 228 } 229 } 230 } 231 232 for(i <- 0 until RenameWidth) { 233 cf_ctrl(i) := MuxCase(csBundle(i), Seq( 234 (stateReg === normal) -> csBundle(i), 235 (stateReg === ext) -> Mux((i.U + numOfUop -uopRes) < maxNumOfUop.U, csBundle(i.U + numOfUop - uopRes), csBundle(maxNumOfUop - 1)) 236 )) 237 } 238 239 240 val validSimple = Wire(Vec(DecodeWidth - 1, Bool())) 241 validSimple.zip(io.validFromIBuf.drop(1).zip(io.isComplex)).map{ case (dst, (src1, src2)) => dst := src1 && !src2 } 242 val notInf = Wire(Vec(DecodeWidth - 1, Bool())) 243 notInf.zip(io.validFromIBuf.drop(1).zip(validSimple)).map{ case (dst, (src1, src2)) => dst := !src1 || src2 } 244 val notInfVec = Wire(Vec(DecodeWidth, Bool())) 245 notInfVec.drop(1).zip(0 until DecodeWidth - 1).map{ case (dst, i) => dst := Cat(notInf.take(i + 1)).andR} 246 notInfVec(0) := true.B 247 248 complexNum := 1.U 249 validToRename.map{ case dst => dst := false.B } 250 readyToIBuf .map{ case dst => dst := false.B } 251 switch(stateReg) { 252 is(normal) { 253 when(!io.validFromIBuf(0)) { 254 complexNum := 1.U 255 validToRename(0) := false.B 256 for (i <- 1 until RenameWidth) { 257 validToRename(i) := notInfVec(i - 1) && validSimple(i - 1) 258 } 259 readyToIBuf(0) := io.readyFromRename(0) 260 for(i <- 1 until DecodeWidth) { 261 readyToIBuf(i) := notInfVec(i - 1) && validSimple(i - 1) && io.readyFromRename(i) 262 } 263 }.elsewhen(numOfUop > readyCounter) { 264 complexNum := Mux(readyCounter === 0.U, 1.U, readyCounter) 265 for (i <- 0 until RenameWidth) { 266 validToRename(i) := Mux(readyCounter > i.U, true.B, false.B) 267 } 268 readyToIBuf.map{ case dst => dst := false.B } 269 }.otherwise { 270 complexNum := numOfUop 271 for (i <- 0 until RenameWidth) { 272 validToRename(i) := Mux(complexNum > i.U, true.B, validSimple(i.U - complexNum) && notInfVec(i.U - complexNum) && io.readyFromRename(i)) 273 } 274 readyToIBuf(0) := true.B 275 for (i <- 1 until DecodeWidth) { 276 readyToIBuf(i) := Mux(RenameWidth.U - complexNum >= i.U, notInfVec(i - 1) && validSimple(i - 1) && io.readyFromRename(i), false.B) 277 } 278 } 279 } 280 is(ext) { 281 when(!io.validFromIBuf(0)) { 282 complexNum := 1.U 283 validToRename.map{ case dst => dst := false.B } 284 readyToIBuf.map{ case dst => dst := true.B } 285 }.elsewhen(uopRes > readyCounter) { 286 complexNum := Mux(readyCounter === 0.U, 1.U, readyCounter) 287 for (i <- 0 until RenameWidth) { 288 validToRename(i) := Mux(readyCounter > i.U, true.B, false.B) 289 } 290 readyToIBuf.map{ case dst => dst := false.B } 291 }.otherwise { 292 complexNum := uopRes 293 for (i <- 0 until RenameWidth) { 294 validToRename(i) := Mux(complexNum > i.U, true.B, validSimple(i.U - complexNum) && notInfVec(i.U - complexNum) && io.readyFromRename(i)) 295 } 296 readyToIBuf(0) := true.B 297 for (i <- 1 until DecodeWidth) { 298 readyToIBuf(i) := Mux(RenameWidth.U - complexNum >= i.U, notInfVec(i - 1) && validSimple(i - 1) && io.readyFromRename(i), false.B) 299 } 300 } 301 } 302 } 303 304 io.deq.cf_ctrl := cf_ctrl 305 io.deq.isVset := isVset_u 306 io.deq.complexNum := complexNum 307 io.deq.validToRename := validToRename 308 io.deq.readyToIBuf := readyToIBuf 309 310} 311 312