diff --git a/chisel/playground/src/CpuConfig.scala b/chisel/playground/src/CpuConfig.scala index d28f937..1c22095 100644 --- a/chisel/playground/src/CpuConfig.scala +++ b/chisel/playground/src/CpuConfig.scala @@ -6,7 +6,7 @@ case class CpuConfig( val build: Boolean = false, // 是否为build模式 // 指令集 val isRV32: Boolean = false, // 是否为RV32 - val hasMExtension: Boolean = false, // 是否有乘除法单元 + val hasMExtension: Boolean = true, // 是否有乘除法单元 // 特权模式 val hasSMode: Boolean = false, // 是否有S模式 val hasUMode: Boolean = false, // 是否有U模式 diff --git a/chisel/playground/src/pipeline/decoder/Decoder.scala b/chisel/playground/src/pipeline/decoder/Decoder.scala index bec9bab..aa66bf3 100644 --- a/chisel/playground/src/pipeline/decoder/Decoder.scala +++ b/chisel/playground/src/pipeline/decoder/Decoder.scala @@ -21,7 +21,7 @@ class Decoder extends Module with HasInstrType { val instrType :: fuType :: fuOpType :: Nil = ListLookup(inst, Instructions.DecodeDefault, Instructions.DecodeTable) - val SrcTypeTable = Seq( + val srcTypeTable = Seq( InstrI -> (SrcType.reg, SrcType.imm), InstrR -> (SrcType.reg, SrcType.reg), InstrS -> (SrcType.reg, SrcType.reg), @@ -31,8 +31,8 @@ class Decoder extends Module with HasInstrType { InstrJ -> (SrcType.pc, SrcType.imm), InstrN -> (SrcType.pc, SrcType.imm) ) - val src1Type = LookupTree(instrType, SrcTypeTable.map(p => (p._1, p._2._1))) - val src2Type = LookupTree(instrType, SrcTypeTable.map(p => (p._1, p._2._2))) + val src1Type = LookupTree(instrType, srcTypeTable.map(p => (p._1, p._2._1))) + val src2Type = LookupTree(instrType, srcTypeTable.map(p => (p._1, p._2._2))) val (rs, rt, rd) = (inst(19, 15), inst(24, 20), inst(11, 7)) @@ -44,8 +44,8 @@ class Decoder extends Module with HasInstrType { io.out.info.reg2_raddr := Mux(io.out.info.reg2_ren, rt, 0.U) io.out.info.fusel := fuType io.out.info.op := fuOpType - io.out.info.reg_wen := isrfWen(instrType) - io.out.info.reg_waddr := Mux(isrfWen(instrType), rd, 0.U) + io.out.info.reg_wen := isrfWen(instrType) + io.out.info.reg_waddr := Mux(isrfWen(instrType), rd, 0.U) io.out.info.imm := LookupTree( instrType, Seq( diff --git a/chisel/playground/src/pipeline/execute/Div.scala b/chisel/playground/src/pipeline/execute/Div.scala index 8623443..572dbcb 100644 --- a/chisel/playground/src/pipeline/execute/Div.scala +++ b/chisel/playground/src/pipeline/execute/Div.scala @@ -12,14 +12,14 @@ class SignedDiv extends BlackBox with HasBlackBoxResource { // 除数 val s_axis_divisor_tvalid = Input(Bool()) val s_axis_divisor_tready = Output(Bool()) - val s_axis_divisor_tdata = Input(UInt(DATA_WID.W)) + val s_axis_divisor_tdata = Input(UInt(XLEN.W)) // 被除数 val s_axis_dividend_tvalid = Input(Bool()) val s_axis_dividend_tready = Output(Bool()) - val s_axis_dividend_tdata = Input(UInt(DATA_WID.W)) + val s_axis_dividend_tdata = Input(UInt(XLEN.W)) // 结果 val m_axis_dout_tvalid = Output(Bool()) - val m_axis_dout_tdata = Output(UInt(64.W)) + val m_axis_dout_tdata = Output(UInt((2 * XLEN).W)) }) } @@ -29,27 +29,27 @@ class UnsignedDiv extends BlackBox with HasBlackBoxResource { // 除数 val s_axis_divisor_tvalid = Input(Bool()) val s_axis_divisor_tready = Output(Bool()) - val s_axis_divisor_tdata = Input(UInt(DATA_WID.W)) + val s_axis_divisor_tdata = Input(UInt(XLEN.W)) // 被除数 val s_axis_dividend_tvalid = Input(Bool()) val s_axis_dividend_tready = Output(Bool()) - val s_axis_dividend_tdata = Input(UInt(DATA_WID.W)) + val s_axis_dividend_tdata = Input(UInt(XLEN.W)) // 结果 val m_axis_dout_tvalid = Output(Bool()) - val m_axis_dout_tdata = Output(UInt(64.W)) + val m_axis_dout_tdata = Output(UInt((2 * XLEN).W)) }) } class Div(implicit config: CpuConfig) extends Module { val io = IO(new Bundle { - val src1 = Input(UInt(DATA_WID.W)) - val src2 = Input(UInt(DATA_WID.W)) + val src1 = Input(UInt(XLEN.W)) + val src2 = Input(UInt(XLEN.W)) val signed = Input(Bool()) val start = Input(Bool()) val allow_to_go = Input(Bool()) val ready = Output(Bool()) - val result = Output(UInt(64.W)) + val result = Output(UInt((2 * XLEN).W)) }) if (config.build) { @@ -118,9 +118,9 @@ class Div(implicit config: CpuConfig) extends Module { unsignedDiv.m_axis_dout_tvalid || unsignedDiv_done ) val signedRes = - Cat(signedDiv.m_axis_dout_tdata(DATA_WID - 1, 0), signedDiv.m_axis_dout_tdata(64 - 1, DATA_WID)) + Cat(signedDiv.m_axis_dout_tdata(XLEN - 1, 0), signedDiv.m_axis_dout_tdata((2 * XLEN) - 1, XLEN)) val unsignedRes = - Cat(unsignedDiv.m_axis_dout_tdata(DATA_WID - 1, 0), unsignedDiv.m_axis_dout_tdata(64 - 1, DATA_WID)) + Cat(unsignedDiv.m_axis_dout_tdata(XLEN - 1, 0), unsignedDiv.m_axis_dout_tdata((2 * XLEN) - 1, XLEN)) io.result := Mux(io.signed, signedRes, unsignedRes) } else { val cnt = RegInit(0.U(log2Ceil(config.divClockNum + 1).W)) @@ -134,24 +134,28 @@ class Div(implicit config: CpuConfig) extends Module { val div_signed = io.signed - val dividend_signed = io.src1(31) & div_signed - val divisor_signed = io.src2(31) & div_signed + val dividend_signed = io.src1(XLEN - 1) & div_signed + val divisor_signed = io.src2(XLEN - 1) & div_signed val dividend_abs = Mux(dividend_signed, (-io.src1).asUInt, io.src1.asUInt) val divisor_abs = Mux(divisor_signed, (-io.src2).asUInt, io.src2.asUInt) - val quotient_signed = (io.src1(31) ^ io.src2(31)) & div_signed - val remainder_signed = io.src1(31) & div_signed + val quotient_signed = (io.src1(XLEN - 1) ^ io.src2(XLEN - 1)) & div_signed + val remainder_signed = io.src1(XLEN - 1) & div_signed val quotient_abs = dividend_abs / divisor_abs val remainder_abs = dividend_abs - quotient_abs * divisor_abs - val quotient = RegInit(0.S(32.W)) - val remainder = RegInit(0.S(32.W)) + val quotient = RegInit(0.S(XLEN.W)) + val remainder = RegInit(0.S(XLEN.W)) when(io.start) { quotient := Mux(quotient_signed, (-quotient_abs).asSInt, quotient_abs.asSInt) remainder := Mux(remainder_signed, (-remainder_abs).asSInt, remainder_abs.asSInt) + when(io.src2 === 0.U) { + quotient := (~0.U).asSInt + remainder := io.src1.asSInt + } } io.ready := cnt >= config.divClockNum.U diff --git a/chisel/playground/src/pipeline/execute/Fu.scala b/chisel/playground/src/pipeline/execute/Fu.scala index 185b4ec..8c680cd 100644 --- a/chisel/playground/src/pipeline/execute/Fu.scala +++ b/chisel/playground/src/pipeline/execute/Fu.scala @@ -35,6 +35,7 @@ class Fu(implicit val config: CpuConfig) extends Module { val alu = Seq.fill(config.decoderNum)(Module(new Alu())) val branchCtrl = Module(new BranchCtrl()).io val mou = Module(new Mou()).io + val mdu = Module(new Mdu()).io mou.in.info := io.inst(0).info mou.in.pc := io.inst(0).pc @@ -52,18 +53,34 @@ class Fu(implicit val config: CpuConfig) extends Module { io.branch.target := Mux(branchCtrl_flush, branchCtrl.out.target, mou.out.target) for (i <- 0 until (config.fuNum)) { - alu(i).io.info := io.inst(i).info - alu(i).io.src_info := io.inst(i).src_info + alu(i).io.info := Mux(io.inst(i).info.fusel === FuType.alu, io.inst(i).info, 0.U.asTypeOf(new InstInfo())) + alu(i).io.src_info := Mux(io.inst(i).info.fusel === FuType.alu, io.inst(i).src_info, 0.U.asTypeOf(new SrcInfo())) } - io.stall_req := false.B + val mdu_sel = VecInit( + io.inst(0).info.fusel === FuType.mdu, + io.inst(1).info.fusel === FuType.mdu + ) + + mdu.info := MuxCase( + 0.U.asTypeOf(new InstInfo()), + Seq(mdu_sel(0) -> io.inst(0).info, mdu_sel(1) -> io.inst(1).info) + ) + mdu.src_info := MuxCase( + 0.U.asTypeOf(new SrcInfo()), + Seq(mdu_sel(0) -> io.inst(0).src_info, mdu_sel(1) -> io.inst(1).src_info) + ) + mdu.allow_to_go := io.ctrl.allow_to_go + + io.stall_req := io.inst.map(_.info.fusel === FuType.mdu).reduce(_ || _) && !mdu.ready io.inst(0).result.alu := Mux( ALUOpType.isBru(io.inst(0).info.op), io.inst(0).pc + 4.U, alu(0).io.result ) - io.inst(0).result.mdu := DontCare + io.inst(0).result.mdu := mdu.result + io.inst(1).result.alu := alu(1).io.result - io.inst(1).result.mdu := DontCare + io.inst(1).result.mdu := mdu.result } diff --git a/chisel/playground/src/pipeline/execute/Mdu.scala b/chisel/playground/src/pipeline/execute/Mdu.scala new file mode 100644 index 0000000..54ad772 --- /dev/null +++ b/chisel/playground/src/pipeline/execute/Mdu.scala @@ -0,0 +1,58 @@ +package cpu.pipeline.execute + +import chisel3._ +import chisel3.util._ +import cpu.defines._ +import cpu.defines.Const._ +import cpu.CpuConfig + +class Mdu(implicit config: CpuConfig) extends Module { + val io = IO(new Bundle { + val info = Input(new InstInfo()) + val src_info = Input(new SrcInfo()) + val allow_to_go = Input(Bool()) + + val ready = Output(Bool()) + val result = Output(UInt(DATA_WID.W)) + }) + + val mul = Module(new Mul()).io + val div = Module(new Div()).io + + val valid = io.info.valid + val op = io.info.op + val is_div = MDUOpType.isDiv(op) + val is_w = MDUOpType.isW(op) + + val src1 = io.src_info.src1_data + val src2 = io.src_info.src2_data + + val zeroExtend = ZeroExtend(_: UInt, XLEN + 1) + val signedExtend = SignedExtend(_: UInt, XLEN + 1) + val srcMulConvertTable = Seq( + MDUOpType.mul -> (zeroExtend, zeroExtend), + MDUOpType.mulh -> (signedExtend, signedExtend), + MDUOpType.mulhsu -> (signedExtend, zeroExtend), + MDUOpType.mulhu -> (zeroExtend, zeroExtend) + ) + + mul.src1 := LookupTree(op(1, 0), srcMulConvertTable.map(p => (p._1, p._2._1(src1)))) + mul.src2 := LookupTree(op(1, 0), srcMulConvertTable.map(p => (p._1, p._2._2(src2)))) + mul.start := valid && !is_div + mul.allow_to_go := io.allow_to_go + + val srcDivConvertFunc = (x: UInt) => + Mux(is_w, Mux(MDUOpType.isDivSign(op), SignedExtend(x(31, 0), XLEN), ZeroExtend(x(31, 0), XLEN)), x) + div.src1 := srcDivConvertFunc(src1) + div.src2 := srcDivConvertFunc(src2) + div.signed := MDUOpType.isDivSign(op) + div.start := valid && is_div + div.allow_to_go := io.allow_to_go + + val mul_result = Mux(op(1, 0) === MDUOpType.mul, mul.result(XLEN - 1, 0), mul.result(2 * XLEN - 1, XLEN)) + val div_result = Mux(op(1), div.result(2 * XLEN - 1, XLEN), div.result(XLEN - 1, 0)) + val result = Mux(is_div, div_result, mul_result) + + io.ready := Mux(is_div, div.ready, mul.ready) + io.result := Mux(is_w, SignedExtend(result(31, 0), XLEN), result) +} diff --git a/chisel/playground/src/pipeline/execute/Mul.scala b/chisel/playground/src/pipeline/execute/Mul.scala index f80183b..a736756 100644 --- a/chisel/playground/src/pipeline/execute/Mul.scala +++ b/chisel/playground/src/pipeline/execute/Mul.scala @@ -10,23 +10,22 @@ class SignedMul extends BlackBox with HasBlackBoxResource { val io = IO(new Bundle { val CLK = Input(Clock()) val CE = Input(Bool()) - val A = Input(UInt((DATA_WID + 1).W)) - val B = Input(UInt((DATA_WID + 1).W)) + val A = Input(UInt((XLEN + 1).W)) + val B = Input(UInt((XLEN + 1).W)) - val P = Output(UInt((64 + 2).W)) + val P = Output(UInt(((2 * XLEN) + 2).W)) }) } class Mul(implicit val config: CpuConfig) extends Module { val io = IO(new Bundle { - val src1 = Input(UInt(DATA_WID.W)) - val src2 = Input(UInt(DATA_WID.W)) - val signed = Input(Bool()) + val src1 = Input(UInt((XLEN + 1).W)) + val src2 = Input(UInt((XLEN + 1).W)) val start = Input(Bool()) val allow_to_go = Input(Bool()) val ready = Output(Bool()) - val result = Output(UInt(64.W)) + val result = Output(UInt((2 * XLEN).W)) }) if (config.build) { @@ -43,15 +42,11 @@ class Mul(implicit val config: CpuConfig) extends Module { signedMul.CLK := clock signedMul.CE := io.start - when(io.signed) { - signedMul.A := Cat(io.src1(DATA_WID - 1), io.src1) - signedMul.B := Cat(io.src2(DATA_WID - 1), io.src2) - }.otherwise { - signedMul.A := Cat(0.U(1.W), io.src1) - signedMul.B := Cat(0.U(1.W), io.src2) - } - io.ready := cnt >= config.mulClockNum.U - io.result := signedMul.P(64 - 1, 0) + + signedMul.A := io.src1 + signedMul.B := io.src2 + io.ready := cnt >= config.mulClockNum.U + io.result := signedMul.P((2 * XLEN) - 1, 0) } else { val cnt = RegInit(0.U(log2Ceil(config.mulClockNum + 1).W)) cnt := MuxCase( @@ -62,13 +57,11 @@ class Mul(implicit val config: CpuConfig) extends Module { ) ) - val signed = RegInit(0.U(64.W)) - val unsigned = RegInit(0.U(64.W)) + val signed = RegInit(0.U((2 * XLEN).W)) when(io.start) { - signed := (io.src1.asSInt * io.src2.asSInt).asUInt - unsigned := io.src1 * io.src2 + signed := (io.src1.asSInt * io.src2.asSInt).asUInt } - io.result := Mux(io.signed, signed, unsigned) + io.result := signed io.ready := cnt >= config.mulClockNum.U } }