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.{LookupTree, LookupTreeDefault, 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 srcw = Input(UInt((XLEN/2).W)) 29 val add = Output(UInt(XLEN.W)) 30 val addw = Output(UInt((XLEN/2).W)) 31 }) 32 io.add := io.src(0) + io.src(1) 33 // TODO: why this extra adder? 34 io.addw := io.srcw + io.src(1)(31,0) 35} 36 37class SubModule(implicit p: Parameters) extends XSModule { 38 val io = IO(new Bundle() { 39 val src = Vec(2, Input(UInt(XLEN.W))) 40 val sub = Output(UInt((XLEN+1).W)) 41 }) 42 io.sub := (io.src(0) +& (~io.src(1)).asUInt()) + 1.U 43} 44 45class LeftShiftModule(implicit p: Parameters) extends XSModule { 46 val io = IO(new Bundle() { 47 val shamt = Input(UInt(6.W)) 48 val revShamt = Input(UInt(6.W)) 49 val sllSrc = Input(UInt(XLEN.W)) 50 val sll = Output(UInt(XLEN.W)) 51 val revSll = Output(UInt(XLEN.W)) 52 }) 53 io.sll := io.sllSrc << io.shamt 54 io.revSll := io.sllSrc << io.revShamt 55} 56 57class LeftShiftWordModule(implicit p: Parameters) extends XSModule { 58 val io = IO(new Bundle() { 59 val shamt = Input(UInt(5.W)) 60 val revShamt = Input(UInt(5.W)) 61 val sllSrc = Input(UInt((XLEN/2).W)) 62 val sllw = Output(UInt((XLEN/2).W)) 63 val revSllw = Output(UInt((XLEN/2).W)) 64 }) 65 io.sllw := io.sllSrc << io.shamt 66 io.revSllw := io.sllSrc << io.revShamt 67} 68 69class RightShiftModule(implicit p: Parameters) extends XSModule { 70 val io = IO(new Bundle() { 71 val shamt = Input(UInt(6.W)) 72 val revShamt = Input(UInt(6.W)) 73 val srlSrc, sraSrc = Input(UInt(XLEN.W)) 74 val srl, sra = Output(UInt(XLEN.W)) 75 val revSrl = Output(UInt(XLEN.W)) 76 }) 77 io.srl := io.srlSrc >> io.shamt 78 io.sra := (io.sraSrc.asSInt() >> io.shamt).asUInt() 79 io.revSrl := io.srlSrc >> io.revShamt 80} 81 82class RightShiftWordModule(implicit p: Parameters) extends XSModule { 83 val io = IO(new Bundle() { 84 val shamt = Input(UInt(5.W)) 85 val revShamt = Input(UInt(5.W)) 86 val srlSrc, sraSrc = Input(UInt((XLEN/2).W)) 87 val srlw, sraw = Output(UInt((XLEN/2).W)) 88 val revSrlw = Output(UInt((XLEN/2).W)) 89 }) 90 91 io.srlw := io.srlSrc >> io.shamt 92 io.sraw := (io.sraSrc.asSInt() >> io.shamt).asUInt() 93 io.revSrlw := io.srlSrc >> io.revShamt 94} 95 96 97class MiscResultSelect(implicit p: Parameters) extends XSModule { 98 val io = IO(new Bundle() { 99 val func = Input(UInt(6.W)) 100 val and, or, xor, orcb, orh48, sextb, packh, sexth, packw, revb, rev8, pack = Input(UInt(XLEN.W)) 101 val src = Input(UInt(XLEN.W)) 102 val miscRes = Output(UInt(XLEN.W)) 103 }) 104 105 val logicRes = VecInit(Seq( 106 io.and, 107 io.or, 108 io.xor, 109 io.orcb 110 ))(io.func(2, 1)) 111 val miscRes = VecInit(Seq(io.sextb, io.packh, io.sexth, io.packw))(io.func(1, 0)) 112 val logicBase = Mux(io.func(3), miscRes, logicRes) 113 114 val revRes = VecInit(Seq(io.revb, io.rev8, io.pack, io.orh48))(io.func(1, 0)) 115 val customRes = VecInit(Seq( 116 Cat(0.U(31.W), io.src(31, 0), 0.U(1.W)), 117 Cat(0.U(30.W), io.src(31, 0), 0.U(2.W)), 118 Cat(0.U(29.W), io.src(31, 0), 0.U(3.W)), 119 Cat(0.U(56.W), io.src(15, 8))))(io.func(1, 0)) 120 val logicAdv = Mux(io.func(3), customRes, revRes) 121 122 val mask = Cat(Fill(15, io.func(0)), 1.U(1.W)) 123 val maskedLogicRes = mask & logicRes 124 125 io.miscRes := Mux(io.func(5), maskedLogicRes, Mux(io.func(4), logicAdv, logicBase)) 126} 127 128class ShiftResultSelect(implicit p: Parameters) extends XSModule { 129 val io = IO(new Bundle() { 130 val func = Input(UInt(4.W)) 131 val sll, srl, sra, rol, ror, bclr, bset, binv, bext = Input(UInt(XLEN.W)) 132 val shiftRes = Output(UInt(XLEN.W)) 133 }) 134 135 // val leftBit = Mux(io.func(1), io.binv, Mux(io.func(0), io.bset, io.bclr)) 136 // val leftRes = Mux(io.func(2), leftBit, io.sll) 137 // val rightRes = Mux(io.func(1) && io.func(0), io.sra, Mux(io.func(1), io.bext, io.srl)) 138 val resultSource = VecInit(Seq( 139 io.sll, 140 io.sll, 141 io.bclr, 142 io.bset, 143 io.binv, 144 io.srl, 145 io.bext, 146 io.sra 147 )) 148 val simple = resultSource(io.func(2, 0)) 149 150 io.shiftRes := Mux(io.func(3), Mux(io.func(0), io.ror, io.rol), simple) 151} 152 153class WordResultSelect(implicit p: Parameters) extends XSModule { 154 val io = IO(new Bundle() { 155 val func = Input(UInt()) 156 val sllw, srlw, sraw, rolw, rorw, addw, subw = Input(UInt((XLEN/2).W)) 157 val wordRes = Output(UInt(XLEN.W)) 158 }) 159 160 val addsubRes = Mux(!io.func(2) && io.func(1), io.subw, io.addw) 161 val shiftRes = Mux(io.func(2), Mux(io.func(0), io.rorw, io.rolw), 162 Mux(io.func(1), io.sraw, Mux(io.func(0), io.srlw, io.sllw))) 163 val wordRes = Mux(io.func(3), shiftRes, addsubRes) 164 io.wordRes := SignExt(wordRes, XLEN) 165} 166 167 168class AluResSel(implicit p: Parameters) extends XSModule { 169 val io = IO(new Bundle() { 170 val func = Input(UInt(3.W)) 171 val addRes, shiftRes, miscRes, compareRes, wordRes = Input(UInt(XLEN.W)) 172 val aluRes = Output(UInt(XLEN.W)) 173 }) 174 175 val res = Mux(io.func(2, 1) === 0.U, Mux(io.func(0), io.wordRes, io.shiftRes), 176 Mux(!io.func(2), Mux(io.func(0), io.compareRes, io.addRes), io.miscRes)) 177 io.aluRes := res 178} 179 180class AluDataModule(implicit p: Parameters) extends XSModule { 181 val io = IO(new Bundle() { 182 val src = Vec(2, Input(UInt(XLEN.W))) 183 val func = Input(FuOpType()) 184 val pred_taken, isBranch = Input(Bool()) 185 val result = Output(UInt(XLEN.W)) 186 val taken, mispredict = Output(Bool()) 187 }) 188 val (src1, src2, func) = (io.src(0), io.src(1), io.func) 189 190 val shamt = src2(5, 0) 191 val revShamt = ~src2(5,0) + 1.U 192 193 // slliuw, sll 194 val leftShiftModule = Module(new LeftShiftModule) 195 val sll = leftShiftModule.io.sll 196 val revSll = leftShiftModule.io.revSll 197 leftShiftModule.io.sllSrc := Cat(Fill(32, func(0)), Fill(32, 1.U)) & src1 198 leftShiftModule.io.shamt := shamt 199 leftShiftModule.io.revShamt := revShamt 200 201 // bclr, bset, binv 202 val bitShift = 1.U << src2(5, 0) 203 val bclr = src1 & ~bitShift 204 val bset = src1 | bitShift 205 val binv = src1 ^ bitShift 206 207 // srl, sra, bext 208 val rightShiftModule = Module(new RightShiftModule) 209 val srl = rightShiftModule.io.srl 210 val revSrl = rightShiftModule.io.revSrl 211 val sra = rightShiftModule.io.sra 212 rightShiftModule.io.shamt := shamt 213 rightShiftModule.io.revShamt := revShamt 214 rightShiftModule.io.srlSrc := src1 215 rightShiftModule.io.sraSrc := src1 216 val bext = srl(0) 217 218 val rol = revSrl | sll 219 val ror = srl | revSll 220 221 // addw 222 val addModule = Module(new AddModule) 223 addModule.io.srcw := Mux(!func(2) && func(0), ZeroExt(src1(0), XLEN), src1(31, 0)) 224 val addwResultAll = VecInit(Seq( 225 ZeroExt(addModule.io.addw(0), XLEN), 226 ZeroExt(addModule.io.addw(7, 0), XLEN), 227 ZeroExt(addModule.io.addw(15, 0), XLEN), 228 SignExt(addModule.io.addw(15, 0), XLEN) 229 )) 230 val addw = Mux(func(2), addwResultAll(func(1, 0)), addModule.io.addw) 231 232 // subw 233 val subModule = Module(new SubModule) 234 val subw = subModule.io.sub 235 236 // sllw 237 val leftShiftWordModule = Module(new LeftShiftWordModule) 238 val sllw = leftShiftWordModule.io.sllw 239 val revSllw = leftShiftWordModule.io.revSllw 240 leftShiftWordModule.io.sllSrc := src1 241 leftShiftWordModule.io.shamt := shamt 242 leftShiftWordModule.io.revShamt := revShamt 243 244 val rightShiftWordModule = Module(new RightShiftWordModule) 245 val srlw = rightShiftWordModule.io.srlw 246 val revSrlw = rightShiftWordModule.io.revSrlw 247 val sraw = rightShiftWordModule.io.sraw 248 rightShiftWordModule.io.shamt := shamt 249 rightShiftWordModule.io.revShamt := revShamt 250 rightShiftWordModule.io.srlSrc := src1 251 rightShiftWordModule.io.sraSrc := src1 252 253 val rolw = revSrlw | sllw 254 val rorw = srlw | revSllw 255 256 // add 257 val wordMaskAddSource = Cat(Fill(32, func(0)), Fill(32, 1.U)) & src1 258 val shaddSource = VecInit(Seq( 259 Cat(wordMaskAddSource(62, 0), 0.U(1.W)), 260 Cat(wordMaskAddSource(61, 0), 0.U(2.W)), 261 Cat(wordMaskAddSource(60, 0), 0.U(3.W)), 262 Cat(wordMaskAddSource(59, 0), 0.U(4.W)) 263 )) 264 val sraddSource = VecInit(Seq( 265 ZeroExt(src1(63, 29), XLEN), 266 ZeroExt(src1(63, 30), XLEN), 267 ZeroExt(src1(63, 31), XLEN), 268 ZeroExt(src1(63, 32), XLEN) 269 )) 270 // TODO: use decoder or other libraries to optimize timing 271 // Now we assume shadd has the worst timing. 272 addModule.io.src(0) := Mux(func(3), shaddSource(func(2, 1)), 273 Mux(func(2), sraddSource(func(1, 0)), 274 Mux(func(1), ZeroExt(src1(0), XLEN), wordMaskAddSource)) 275 ) 276 addModule.io.src(1) := src2 277 val add = addModule.io.add 278 279 // sub 280 val sub = subModule.io.sub 281 subModule.io.src(0) := src1 282 subModule.io.src(1) := src2 283 val sgtu = sub(XLEN) 284 val sltu = !sgtu 285 val slt = src1(XLEN - 1) ^ src2(XLEN - 1) ^ sltu 286 val maxMin = Mux(slt ^ func(0), src2, src1) 287 val maxMinU = Mux((sgtu && func(0)) || ~(sgtu && func(0)), src2, src1) 288 val compareRes = Mux(func(2), Mux(func(1), maxMin, maxMinU), Mux(func(1), slt, Mux(func(0), sltu, sub))) 289 290 // logic 291 val logicSrc2 = Mux(!func(5) && func(0), ~src2, src2) 292 val and = src1 & logicSrc2 293 val or = src1 | logicSrc2 294 val xor = src1 ^ logicSrc2 295 val orcb = Cat((7 to 0).map(i => Fill(8, src1(i * 8 + 7, i * 8).orR))) 296 val orh48 = Cat(src1(63, 8), 0.U(8.W)) | src2 297 298 val sextb = SignExt(src1(7, 0), XLEN) 299 val packh = Cat(src2(7,0), src1(7,0)) 300 val sexth = SignExt(src1(15, 0), XLEN) 301 val packw = SignExt(Cat(src2(15, 0), src1(15, 0)), XLEN) 302 303 val revb = Cat((7 to 0).map(i => Reverse(src1(8 * i + 7, 8 * i)))) 304 val pack = Cat(src2(31, 0), src1(31, 0)) 305 val rev8 = Cat((0 until 8).map(i => src1(8 * i + 7, 8 * i))) 306 307 // branch 308 val branchOpTable = List( 309 ALUOpType.getBranchType(ALUOpType.beq) -> !xor.orR, 310 ALUOpType.getBranchType(ALUOpType.blt) -> slt, 311 ALUOpType.getBranchType(ALUOpType.bltu) -> sltu 312 ) 313 val taken = LookupTree(ALUOpType.getBranchType(func), branchOpTable) ^ ALUOpType.isBranchInvert(func) 314 315 // Result Select 316 val shiftResSel = Module(new ShiftResultSelect) 317 shiftResSel.io.func := func(3, 0) 318 shiftResSel.io.sll := sll 319 shiftResSel.io.srl := srl 320 shiftResSel.io.sra := sra 321 shiftResSel.io.rol := rol 322 shiftResSel.io.ror := ror 323 shiftResSel.io.bclr := bclr 324 shiftResSel.io.binv := binv 325 shiftResSel.io.bset := bset 326 shiftResSel.io.bext := bext 327 val shiftRes = shiftResSel.io.shiftRes 328 329 val miscResSel = Module(new MiscResultSelect) 330 miscResSel.io.func := func(5, 0) 331 miscResSel.io.and := and 332 miscResSel.io.or := or 333 miscResSel.io.xor := xor 334 miscResSel.io.orcb := orcb 335 miscResSel.io.orh48 := orh48 336 miscResSel.io.sextb := sextb 337 miscResSel.io.packh := packh 338 miscResSel.io.sexth := sexth 339 miscResSel.io.packw := packw 340 miscResSel.io.revb := revb 341 miscResSel.io.rev8 := rev8 342 miscResSel.io.pack := pack 343 miscResSel.io.src := src1 344 val miscRes = miscResSel.io.miscRes 345 346 val wordResSel = Module(new WordResultSelect) 347 wordResSel.io.func := func 348 wordResSel.io.addw := addw 349 wordResSel.io.subw := subw 350 wordResSel.io.sllw := sllw 351 wordResSel.io.srlw := srlw 352 wordResSel.io.sraw := sraw 353 wordResSel.io.rolw := rolw 354 wordResSel.io.rorw := rorw 355 val wordRes = wordResSel.io.wordRes 356 357 val aluResSel = Module(new AluResSel) 358 aluResSel.io.func := func(6, 4) 359 aluResSel.io.addRes := add 360 aluResSel.io.compareRes := compareRes 361 aluResSel.io.shiftRes := shiftRes 362 aluResSel.io.miscRes := miscRes 363 aluResSel.io.wordRes := wordRes 364 val aluRes = aluResSel.io.aluRes 365 366 io.result := aluRes 367 io.taken := taken 368 io.mispredict := (io.pred_taken ^ taken) && io.isBranch 369} 370 371class Alu(implicit p: Parameters) extends FUWithRedirect { 372 373 val uop = io.in.bits.uop 374 375 val isBranch = ALUOpType.isBranch(io.in.bits.uop.ctrl.fuOpType) 376 val dataModule = Module(new AluDataModule) 377 378 dataModule.io.src := io.in.bits.src.take(2) 379 dataModule.io.func := io.in.bits.uop.ctrl.fuOpType 380 dataModule.io.pred_taken := uop.cf.pred_taken 381 dataModule.io.isBranch := isBranch 382 383 redirectOutValid := io.out.valid && isBranch 384 redirectOut := DontCare 385 redirectOut.level := RedirectLevel.flushAfter 386 redirectOut.roqIdx := uop.roqIdx 387 redirectOut.ftqIdx := uop.cf.ftqPtr 388 redirectOut.ftqOffset := uop.cf.ftqOffset 389 redirectOut.cfiUpdate.isMisPred := dataModule.io.mispredict 390 redirectOut.cfiUpdate.taken := dataModule.io.taken 391 redirectOut.cfiUpdate.predTaken := uop.cf.pred_taken 392 393 io.in.ready := io.out.ready 394 io.out.valid := io.in.valid 395 io.out.bits.uop <> io.in.bits.uop 396 io.out.bits.data := dataModule.io.result 397} 398