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.fu 18 19import chipsalliance.rocketchip.config.Parameters 20import chisel3._ 21import chisel3.util._ 22import utils.{LookupTreeDefault, LookupTree, ParallelMux, SignExt, ZeroExt} 23import xiangshan._ 24 25class AddModule(implicit p: Parameters) extends XSModule { 26 val io = IO(new Bundle() { 27 val src = Vec(2, Input(UInt(XLEN.W))) 28 val out = Output(UInt((XLEN+1).W)) 29 }) 30 io.out := io.src(0) +& io.src(1) 31} 32 33class SubModule(implicit p: Parameters) extends XSModule { 34 val io = IO(new Bundle() { 35 val src = Vec(2, Input(UInt(XLEN.W))) 36 val out = Output(UInt((XLEN+1).W)) 37 }) 38 io.out := (io.src(0) +& (~io.src(1)).asUInt()) + 1.U 39} 40 41class LeftShiftModule(implicit p: Parameters) extends XSModule { 42 val io = IO(new Bundle() { 43 val shamt = Input(UInt(6.W)) 44 val sllSrc = Input(UInt(XLEN.W)) 45 val sll = Output(UInt(XLEN.W)) 46 }) 47 io.sll := (io.sllSrc << io.shamt)(XLEN - 1, 0) 48} 49 50class RightShiftModule(implicit p: Parameters) extends XSModule { 51 val io = IO(new Bundle() { 52 val shamt = Input(UInt(6.W)) 53 val srlSrc, sraSrc = Input(UInt(XLEN.W)) 54 val srl_l, srl_w, sra_l, sra_w = Output(UInt(XLEN.W)) 55 }) 56 io.srl_l := io.srlSrc >> io.shamt 57 io.srl_w := io.srlSrc(31, 0) >> io.shamt 58 io.sra_l := (io.sraSrc.asSInt() >> io.shamt).asUInt() 59 io.sra_w := (Cat(Fill(32, io.sraSrc(31)), io.sraSrc(31, 0)).asSInt() >> io.shamt).asUInt() 60} 61 62class RotateShiftModule(implicit p: Parameters) extends XSModule { 63 val io = IO(new Bundle() { 64 val shamt = Input(UInt(6.W)) 65 val roSrc = Input(UInt(XLEN.W)) 66 val rol_l, rol_w, ror_l, ror_w = Output(UInt(XLEN.W)) 67 }) 68 io.rol_l := io.roSrc << io.shamt | io.roSrc >> ((~io.shamt).asUInt()+&1.U) 69 io.rol_w := (io.roSrc << io.shamt | io.roSrc >> (32.U-io.shamt))(31,0) 70 io.ror_l := io.roSrc>>io.shamt | io.roSrc << ((~io.shamt).asUInt()+&1.U) 71 io.ror_w := (io.roSrc>>io.shamt | io.roSrc << (32.U-io.shamt))(31,0) 72} 73 74class MiscResultSelect(implicit p: Parameters) extends XSModule { 75 val io = IO(new Bundle() { 76 val func = Input(UInt()) 77 val andn, orn, xnor, and, or, xor, sltu, slt, maxMin, maxMinU, sextb, sexth, zexth, rev8, orcb = Input(UInt(XLEN.W)) 78 val miscRes = Output(UInt(XLEN.W)) 79 }) 80 81 val (func, andn, orn, xnor, and, or, xor, sltu, slt, maxMin, maxMinU, sextb, sexth, zexth, rev8, orcb) = 82 (io.func, io.andn, io.orn, io.xnor, io.and, io.or, io.xor, io.sltu, io.slt, io.maxMin, io.maxMinU, io.sextb, io.sexth, io.zexth, io.rev8, io.orcb) 83 84 val baseMisc = ParallelMux(List( 85 ALUOpType.andn -> andn, 86 ALUOpType.and -> and, 87 ALUOpType.orn -> orn, 88 ALUOpType.or -> or, 89 ALUOpType.xnor -> xnor, 90 ALUOpType.xor -> xor 91 ).map(x => (x._1(2, 0) === io.func(2, 0), x._2))) 92 93 val bitMisc = ParallelMux(List( 94 ALUOpType.sext_b -> sextb, 95 ALUOpType.sext_h -> sexth, 96 ALUOpType.zext_h -> zexth, 97 ALUOpType.orc_b -> orcb, 98 ALUOpType.rev8 -> rev8 99 ).map(x => (x._1(2, 0) === io.func(2, 0), x._2))) 100 101 val compMisc = Mux(func(2), 102 Mux(func(1), maxMinU, maxMin), 103 Mux(func(1), sltu, slt)) 104 105 io.miscRes := Mux(func(4), compMisc, Mux(func(3), bitMisc, baseMisc)) 106} 107 108class ShiftResultSelect(implicit p: Parameters) extends XSModule { 109 val io = IO(new Bundle() { 110 val func = Input(UInt()) 111 val sll, srl, sra, rol, ror, bclr, bset, binv, bext = Input(UInt(XLEN.W)) 112 val shiftRes = Output(UInt(XLEN.W)) 113 }) 114 115 val (func, sll, srl, sra, rol, ror, bclr, bset, binv, bext) = 116 (io.func, io.sll, io.srl, io.sra, io.rol, io.ror, io.bclr, io.bset, io.binv, io.bext) 117 118 val singleBitRes = ParallelMux(List( 119 ALUOpType.bclr -> bclr, 120 ALUOpType.binv -> binv, 121 ALUOpType.bset -> bset, 122 ALUOpType.bext -> bext 123 ).map(x => (x._1(1, 0) === io.func(1, 0), x._2))) 124 125 val lrShiftRes = Mux(func(1), Mux(func(0), sra, srl), sll) 126 val rotateShiftRes = Mux(func(3), ror, rol) 127 128 io.shiftRes := Mux(func(4), rotateShiftRes, Mux(func(2), singleBitRes, lrShiftRes)) 129} 130 131 132class AluResSel(implicit p: Parameters) extends XSModule { 133 val io = IO(new Bundle() { 134 val func = Input(UInt()) 135 // val addSubRes, shiftRes, miscRes, countRes = Input(UInt(XLEN.W)) 136 val addSubRes, shiftRes, miscRes = Input(UInt(XLEN.W)) 137 val aluRes = Output(UInt(XLEN.W)) 138 }) 139 140 val res = Mux(io.func(6), 141 io.shiftRes, 142 Mux(io.func(5), io.addSubRes, io.miscRes) 143 ) 144 val h32 = Mux(io.func(7), Fill(32, res(31)), res(63, 32)) 145 io.aluRes := Cat(h32, res(31, 0)) 146} 147 148class AluDataModule(implicit p: Parameters) extends XSModule { 149 val io = IO(new Bundle() { 150 val src = Vec(2, Input(UInt(XLEN.W))) 151 val func = Input(FuOpType()) 152 val pred_taken, isBranch = Input(Bool()) 153 val result = Output(UInt(XLEN.W)) 154 val taken, mispredict = Output(Bool()) 155 }) 156 val (src1, src2, func) = (io.src(0), io.src(1), io.func) 157 158 val addModule = Module(new AddModule) 159 addModule.io.src(1) := src2 160 addModule.io.src(0) := ParallelMux(List( 161 "b000".U -> src1, 162 "b001".U -> src1(31,0), 163 "b010".U -> Cat(src1(62,0), 0.U(1.W)), 164 "b011".U -> Cat(src1(30,0), 0.U(1.W)), 165 "b100".U -> Cat(src1(61,0), 0.U(2.W)), 166 "b101".U -> Cat(src1(29,0), 0.U(2.W)), 167 "b110".U -> Cat(src1(60,0), 0.U(3.W)), 168 "b111".U -> Cat(src1(28,0), 0.U(3.W)), 169 ).map(x => (x._1(2, 0) === func(2,0), x._2))) 170 171 172 val subModule = Module(new SubModule) 173 subModule.io.src(0) := src1 174 subModule.io.src(1) := src2 175 val add = addModule.io.out 176 val sub = subModule.io.out 177 178 179 // Misc 180 val andn = ~(src1 & src2) 181 val orn = ~(src1 | src2) 182 val xnor = ~(src1 ^ src2) 183 val and = ~andn 184 val or = ~orn 185 val xor = ~xnor 186 val sltu = !sub(XLEN) 187 val slt = xor(XLEN-1) ^ sltu 188 val maxMin = Mux(slt ^ func(0), src2, src1) 189 val maxMinU = Mux(sltu^ func(0), src2, src1) 190 val sextb = SignExt(src1(7, 0), XLEN) 191 val sexth = SignExt(src1(15, 0), XLEN) 192 val zexth = ZeroExt(src1(15, 0), XLEN) 193 val rev8 = Cat(src1(7,0), src1(15,8), src1(23,16), src1(31,24), 194 src1(39,32), src1(47,40), src1(55,48), src1(63,56)) 195 val orcb = Cat(Reverse(src1(63,56)), Reverse(src1(55,48)), Reverse(src1(47,40)), Reverse(src1(39,32)), 196 Reverse(src1(31,24)), Reverse(src1(23,16)), Reverse(src1(15,8)), Reverse(src1(7,0))) 197 198 val branchOpTable = List( 199 ALUOpType.getBranchType(ALUOpType.beq) -> !xor.orR, 200 ALUOpType.getBranchType(ALUOpType.blt) -> slt, 201 ALUOpType.getBranchType(ALUOpType.bltu) -> sltu 202 ) 203 val taken = LookupTree(ALUOpType.getBranchType(func), branchOpTable) ^ ALUOpType.isBranchInvert(func) 204 205 206 // Shift 207 val isW = ALUOpType.isWordOp(func) 208 val shamt = Cat(!isW && src2(5), src2(4, 0)) 209 210 val leftShiftModule = Module(new LeftShiftModule) 211 leftShiftModule.io.sllSrc := Mux(func(2), 1.U, Mux(func(0), src1(31,0), src1)) 212 leftShiftModule.io.shamt := shamt 213 val sll = leftShiftModule.io.sll 214 val bset = src1 | sll 215 val bclr = src1 & ~sll 216 val binv = src1 ^ sll 217 218 219 val rightShiftModule = Module(new RightShiftModule) 220 rightShiftModule.io.shamt := shamt 221 rightShiftModule.io.srlSrc := src1 222 rightShiftModule.io.sraSrc := src1 223 val srl = Mux(isW, rightShiftModule.io.srl_w, rightShiftModule.io.srl_l) 224 val sra = Mux(isW, rightShiftModule.io.sra_w, rightShiftModule.io.sra_l) 225 val bext = srl(0) 226 227 val rotateShiftModule = Module(new RotateShiftModule) 228 rotateShiftModule.io.shamt := Mux(isW, src2(4,0), src2(5,0)) 229 rotateShiftModule.io.roSrc := Mux(isW, src1(31,0), src1) 230 val rol = Mux(isW, rotateShiftModule.io.rol_w, rotateShiftModule.io.rol_l) 231 val ror = Mux(isW, rotateShiftModule.io.ror_w, rotateShiftModule.io.ror_l) 232 233 val miscResSel = Module(new MiscResultSelect) 234 miscResSel.io.func := func(4, 0) 235 miscResSel.io.andn := andn 236 miscResSel.io.orn := orn 237 miscResSel.io.xnor := xnor 238 miscResSel.io.and := and 239 miscResSel.io.or := or 240 miscResSel.io.xor := xor 241 miscResSel.io.sltu := sltu 242 miscResSel.io.slt := slt 243 miscResSel.io.maxMin := maxMin 244 miscResSel.io.maxMinU := maxMinU 245 miscResSel.io.sextb := sextb 246 miscResSel.io.sexth := sexth 247 miscResSel.io.zexth := zexth 248 miscResSel.io.rev8 := rev8 249 miscResSel.io.orcb := orcb 250 val miscRes = miscResSel.io.miscRes 251 252 val addSubRes = Mux(func(3), sub, add) 253 254 val shiftResSel = Module(new ShiftResultSelect) 255 shiftResSel.io.func := func(4,0) 256 shiftResSel.io.sll := sll 257 shiftResSel.io.srl := srl 258 shiftResSel.io.sra := sra 259 shiftResSel.io.rol := rol 260 shiftResSel.io.ror := ror 261 shiftResSel.io.bclr := bclr 262 shiftResSel.io.binv := binv 263 shiftResSel.io.bset := bset 264 shiftResSel.io.bext := bext 265 val shiftRes = shiftResSel.io.shiftRes 266 267 val aluResSel = Module(new AluResSel) 268 aluResSel.io.func := func 269 aluResSel.io.addSubRes := addSubRes 270 aluResSel.io.shiftRes := shiftRes 271 aluResSel.io.miscRes := miscRes 272 val aluRes = aluResSel.io.aluRes 273 274 io.result := aluRes 275 io.taken := taken 276 io.mispredict := (io.pred_taken ^ taken) && io.isBranch 277} 278 279class Alu(implicit p: Parameters) extends FUWithRedirect { 280 281 val (src1, src2, func, pc, uop) = ( 282 io.in.bits.src(0), 283 io.in.bits.src(1), 284 io.in.bits.uop.ctrl.fuOpType, 285 SignExt(io.in.bits.uop.cf.pc, AddrBits), 286 io.in.bits.uop 287 ) 288 289 val valid = io.in.valid 290 val isBranch = ALUOpType.isBranch(func) 291 val dataModule = Module(new AluDataModule) 292 293 dataModule.io.src(0) := src1 294 dataModule.io.src(1) := src2 295 dataModule.io.func := func 296 dataModule.io.pred_taken := uop.cf.pred_taken 297 dataModule.io.isBranch := isBranch 298 299 redirectOutValid := io.out.valid && isBranch 300 redirectOut := DontCare 301 redirectOut.level := RedirectLevel.flushAfter 302 redirectOut.roqIdx := uop.roqIdx 303 redirectOut.ftqIdx := uop.cf.ftqPtr 304 redirectOut.ftqOffset := uop.cf.ftqOffset 305 redirectOut.cfiUpdate.isMisPred := dataModule.io.mispredict 306 redirectOut.cfiUpdate.taken := dataModule.io.taken 307 redirectOut.cfiUpdate.predTaken := uop.cf.pred_taken 308 309 io.in.ready := io.out.ready 310 io.out.valid := valid 311 io.out.bits.uop <> io.in.bits.uop 312 io.out.bits.data := dataModule.io.result 313} 314