1package xiangshan.backend.fu 2 3import chisel3._ 4import chisel3.util._ 5import utils.{LookupTree, ParallelMux, SignExt, ZeroExt} 6import xiangshan._ 7import xiangshan.backend.ALUOpType 8 9class AddModule extends XSModule { 10 val io = IO(new Bundle() { 11 val src1, src2 = Input(UInt(XLEN.W)) 12 val out = Output(UInt((XLEN+1).W)) 13 }) 14 io.out := io.src1 +& io.src2 15} 16 17class SubModule extends XSModule { 18 val io = IO(new Bundle() { 19 val src1, src2 = Input(UInt(XLEN.W)) 20 val out = Output(UInt((XLEN+1).W)) 21 }) 22 io.out := (io.src1 +& (~io.src2).asUInt()) + 1.U 23} 24 25class LeftShiftModule extends XSModule { 26 val io = IO(new Bundle() { 27 val shamt = Input(UInt(6.W)) 28 val sllSrc = Input(UInt(XLEN.W)) 29 val sll = Output(UInt(XLEN.W)) 30 }) 31 io.sll := (io.sllSrc << io.shamt)(XLEN - 1, 0) 32} 33 34class RightShiftModule extends XSModule { 35 val io = IO(new Bundle() { 36 val shamt = Input(UInt(6.W)) 37 val srlSrc, sraSrc = Input(UInt(XLEN.W)) 38 val srl, sra = Output(UInt(XLEN.W)) 39 }) 40 io.srl := io.srlSrc >> io.shamt 41 io.sra := (io.sraSrc.asSInt() >> io.shamt).asUInt() 42} 43 44class MiscResultSelect extends XSModule { 45 val io = IO(new Bundle() { 46 val func = Input(UInt()) 47 val sll, slt, sltu, xor, srl, or, and, sra = Input(UInt(XLEN.W)) 48 val miscRes = Output(UInt(XLEN.W)) 49 50 }) 51 io.miscRes := ParallelMux(List( 52 ALUOpType.and -> io.and, 53 ALUOpType.or -> io.or, 54 ALUOpType.xor -> io.xor, 55 ALUOpType.slt -> ZeroExt(io.slt, XLEN), 56 ALUOpType.sltu -> ZeroExt(io.sltu, XLEN), 57 ALUOpType.srl -> io.srl, 58 ALUOpType.sll -> io.sll, 59 ALUOpType.sra -> io.sra 60 ).map(x => (x._1 === io.func(3, 0), x._2))) 61} 62 63class AluResSel extends XSModule { 64 val io = IO(new Bundle() { 65 val func = Input(UInt()) 66 val isSub = Input(Bool()) 67 val addRes, subRes, miscRes = Input(UInt(XLEN.W)) 68 val aluRes = Output(UInt(XLEN.W)) 69 }) 70 val isAddSub = ALUOpType.isAddSub(io.func) 71 val res = Mux(ALUOpType.isAddSub(io.func), 72 Mux(io.isSub, io.subRes, io.addRes), 73 io.miscRes 74 ) 75 val h32 = Mux(ALUOpType.isWordOp(io.func), Fill(32, res(31)), res(63, 32)) 76 io.aluRes := Cat(h32, res(31, 0)) 77} 78 79class AluDataModule extends XSModule { 80 val io = IO(new Bundle() { 81 val src1, src2 = Input(UInt(XLEN.W)) 82 val func = Input(FuOpType()) 83 val pred_taken, isBranch = Input(Bool()) 84 val result = Output(UInt(XLEN.W)) 85 val taken, mispredict = Output(Bool()) 86 }) 87 val (src1, src2, func) = (io.src1, io.src2, io.func) 88 89 val isAdderSub = (func =/= ALUOpType.add) && (func =/= ALUOpType.addw) 90 val addModule = Module(new AddModule) 91 addModule.io.src1 := src1 92 addModule.io.src2 := src2 93 val subModule = Module(new SubModule) 94 subModule.io.src1 := src1 95 subModule.io.src2 := src2 96 val addRes = addModule.io.out 97 val subRes = subModule.io.out 98 val xorRes = src1 ^ src2 99 val sltu = !subRes(XLEN) 100 val slt = xorRes(XLEN-1) ^ sltu 101 102 val isW = ALUOpType.isWordOp(func) 103 val shamt = Cat(!isW && src2(5), src2(4, 0)) 104 105 val leftShiftModule = Module(new LeftShiftModule) 106 leftShiftModule.io.sllSrc := src1 107 leftShiftModule.io.shamt := shamt 108 109 val rightShiftModule = Module(new RightShiftModule) 110 rightShiftModule.io.shamt := shamt 111 rightShiftModule.io.srlSrc := Cat( 112 Mux(isW, 0.U(32.W), src1(63, 32)), 113 src1(31, 0) 114 ) 115 rightShiftModule.io.sraSrc := Cat( 116 Mux(isW, Fill(32, src1(31)), src1(63, 32)), 117 src1(31, 0) 118 ) 119 120 val sll = leftShiftModule.io.sll 121 val srl = rightShiftModule.io.srl 122 val sra = rightShiftModule.io.sra 123 124 val miscResSel = Module(new MiscResultSelect) 125 miscResSel.io.func := func(3, 0) 126 miscResSel.io.sll := sll 127 miscResSel.io.slt := ZeroExt(slt, XLEN) 128 miscResSel.io.sltu := ZeroExt(sltu, XLEN) 129 miscResSel.io.xor := xorRes 130 miscResSel.io.srl := srl 131 miscResSel.io.or := (src1 | src2) 132 miscResSel.io.and := (src1 & src2) 133 miscResSel.io.sra := sra 134 135 val miscRes = miscResSel.io.miscRes 136 137 val aluResSel = Module(new AluResSel) 138 aluResSel.io.func := func 139 aluResSel.io.isSub := isAdderSub 140 aluResSel.io.addRes := addRes 141 aluResSel.io.subRes := subRes 142 aluResSel.io.miscRes := miscRes 143 val aluRes = aluResSel.io.aluRes 144 145 val branchOpTable = List( 146 ALUOpType.getBranchType(ALUOpType.beq) -> !xorRes.orR, 147 ALUOpType.getBranchType(ALUOpType.blt) -> slt, 148 ALUOpType.getBranchType(ALUOpType.bltu) -> sltu 149 ) 150 val taken = LookupTree(ALUOpType.getBranchType(func), branchOpTable) ^ ALUOpType.isBranchInvert(func) 151 152 io.result := aluRes 153 io.taken := taken 154 io.mispredict := (io.pred_taken ^ taken) && io.isBranch 155} 156 157class Alu extends FunctionUnit with HasRedirectOut { 158 159 val (src1, src2, func, pc, uop) = ( 160 io.in.bits.src(0), 161 io.in.bits.src(1), 162 io.in.bits.uop.ctrl.fuOpType, 163 SignExt(io.in.bits.uop.cf.pc, AddrBits), 164 io.in.bits.uop 165 ) 166 167 val valid = io.in.valid 168 val isBranch = ALUOpType.isBranch(func) 169 val dataModule = Module(new AluDataModule) 170 171 dataModule.io.src1 := src1 172 dataModule.io.src2 := src2 173 dataModule.io.func := func 174 dataModule.io.pred_taken := uop.cf.pred_taken 175 dataModule.io.isBranch := isBranch 176 177 redirectOutValid := io.out.valid && isBranch 178 redirectOut := DontCare 179 redirectOut.level := RedirectLevel.flushAfter 180 redirectOut.roqIdx := uop.roqIdx 181 redirectOut.ftqIdx := uop.cf.ftqPtr 182 redirectOut.ftqOffset := uop.cf.ftqOffset 183 redirectOut.cfiUpdate.isMisPred := dataModule.io.mispredict 184 redirectOut.cfiUpdate.taken := dataModule.io.taken 185 redirectOut.cfiUpdate.predTaken := uop.cf.pred_taken 186 187 io.in.ready := io.out.ready 188 io.out.valid := valid 189 io.out.bits.uop <> io.in.bits.uop 190 io.out.bits.data := dataModule.io.result 191} 192