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, 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 MiscResultSelect(implicit p: Parameters) extends XSModule { 63 val io = IO(new Bundle() { 64 val func = Input(UInt()) 65 val sll, slt, sltu, xor, srl, or, and, sra = Input(UInt(XLEN.W)) 66 val miscRes = Output(UInt(XLEN.W)) 67 68 }) 69 io.miscRes := ParallelMux(List( 70 ALUOpType.and -> io.and, 71 ALUOpType.or -> io.or, 72 ALUOpType.xor -> io.xor, 73 ALUOpType.slt -> ZeroExt(io.slt, XLEN), 74 ALUOpType.sltu -> ZeroExt(io.sltu, XLEN), 75 ALUOpType.srl -> io.srl, 76 ALUOpType.sll -> io.sll, 77 ALUOpType.sra -> io.sra 78 ).map(x => (x._1 === io.func(3, 0), x._2))) 79} 80 81class AluResSel(implicit p: Parameters) extends XSModule { 82 val io = IO(new Bundle() { 83 val func = Input(UInt()) 84 val isSub = Input(Bool()) 85 val addRes, subRes, miscRes = Input(UInt(XLEN.W)) 86 val aluRes = Output(UInt(XLEN.W)) 87 }) 88 val isAddSub = ALUOpType.isAddSub(io.func) 89 val res = Mux(ALUOpType.isAddSub(io.func), 90 Mux(io.isSub, io.subRes, io.addRes), 91 io.miscRes 92 ) 93 val h32 = Mux(ALUOpType.isWordOp(io.func), Fill(32, res(31)), res(63, 32)) 94 io.aluRes := Cat(h32, res(31, 0)) 95} 96 97class AluDataModule(implicit p: Parameters) extends XSModule { 98 val io = IO(new Bundle() { 99 val src = Vec(2, Input(UInt(XLEN.W))) 100 val func = Input(FuOpType()) 101 val pred_taken, isBranch = Input(Bool()) 102 val result = Output(UInt(XLEN.W)) 103 val taken, mispredict = Output(Bool()) 104 }) 105 val (src1, src2, func) = (io.src(0), io.src(1), io.func) 106 107 val isAdderSub = (func =/= ALUOpType.add) && (func =/= ALUOpType.addw) 108 val addModule = Module(new AddModule) 109 addModule.io.src(0) := src1 110 addModule.io.src(1) := src2 111 val subModule = Module(new SubModule) 112 subModule.io.src(0) := src1 113 subModule.io.src(1) := src2 114 val addRes = addModule.io.out 115 val subRes = subModule.io.out 116 val xorRes = src1 ^ src2 117 val sltu = !subRes(XLEN) 118 val slt = xorRes(XLEN-1) ^ sltu 119 120 val isW = ALUOpType.isWordOp(func) 121 val shamt = Cat(!isW && src2(5), src2(4, 0)) 122 123 val leftShiftModule = Module(new LeftShiftModule) 124 leftShiftModule.io.sllSrc := src1 125 leftShiftModule.io.shamt := shamt 126 127 val rightShiftModule = Module(new RightShiftModule) 128 rightShiftModule.io.shamt := shamt 129 rightShiftModule.io.srlSrc := src1 130 rightShiftModule.io.sraSrc := src1 131 132 val sll = leftShiftModule.io.sll 133 val srl = Mux(isW, rightShiftModule.io.srl_w, rightShiftModule.io.srl_l) 134 val sra = Mux(isW, rightShiftModule.io.sra_w, rightShiftModule.io.sra_l) 135 136 val miscResSel = Module(new MiscResultSelect) 137 miscResSel.io.func := func(3, 0) 138 miscResSel.io.sll := sll 139 miscResSel.io.slt := ZeroExt(slt, XLEN) 140 miscResSel.io.sltu := ZeroExt(sltu, XLEN) 141 miscResSel.io.xor := xorRes 142 miscResSel.io.srl := srl 143 miscResSel.io.or := (src1 | src2) 144 miscResSel.io.and := (src1 & src2) 145 miscResSel.io.sra := sra 146 147 val miscRes = miscResSel.io.miscRes 148 149 val aluResSel = Module(new AluResSel) 150 aluResSel.io.func := func 151 aluResSel.io.isSub := isAdderSub 152 aluResSel.io.addRes := addRes 153 aluResSel.io.subRes := subRes 154 aluResSel.io.miscRes := miscRes 155 val aluRes = aluResSel.io.aluRes 156 157 val branchOpTable = List( 158 ALUOpType.getBranchType(ALUOpType.beq) -> !xorRes.orR, 159 ALUOpType.getBranchType(ALUOpType.blt) -> slt, 160 ALUOpType.getBranchType(ALUOpType.bltu) -> sltu 161 ) 162 val taken = LookupTree(ALUOpType.getBranchType(func), branchOpTable) ^ ALUOpType.isBranchInvert(func) 163 164 io.result := aluRes 165 io.taken := taken 166 io.mispredict := (io.pred_taken ^ taken) && io.isBranch 167} 168 169class Alu(implicit p: Parameters) extends FunctionUnit with HasRedirectOut { 170 171 val (src1, src2, func, pc, uop) = ( 172 io.in.bits.src(0), 173 io.in.bits.src(1), 174 io.in.bits.uop.ctrl.fuOpType, 175 SignExt(io.in.bits.uop.cf.pc, AddrBits), 176 io.in.bits.uop 177 ) 178 179 val valid = io.in.valid 180 val isBranch = ALUOpType.isBranch(func) 181 val dataModule = Module(new AluDataModule) 182 183 dataModule.io.src(0) := src1 184 dataModule.io.src(1) := src2 185 dataModule.io.func := func 186 dataModule.io.pred_taken := uop.cf.pred_taken 187 dataModule.io.isBranch := isBranch 188 189 redirectOutValid := io.out.valid && isBranch 190 redirectOut := DontCare 191 redirectOut.level := RedirectLevel.flushAfter 192 redirectOut.roqIdx := uop.roqIdx 193 redirectOut.ftqIdx := uop.cf.ftqPtr 194 redirectOut.ftqOffset := uop.cf.ftqOffset 195 redirectOut.cfiUpdate.isMisPred := dataModule.io.mispredict 196 redirectOut.cfiUpdate.taken := dataModule.io.taken 197 redirectOut.cfiUpdate.predTaken := uop.cf.pred_taken 198 199 io.in.ready := io.out.ready 200 io.out.valid := valid 201 io.out.bits.uop <> io.in.bits.uop 202 io.out.bits.data := dataModule.io.result 203} 204