feat(mdu): 增加M拓展

This commit is contained in:
Liphen 2023-12-03 16:03:39 +08:00
parent bda65bef5b
commit 5f75a0ac89
6 changed files with 121 additions and 49 deletions

View File

@ -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模式

View File

@ -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(

View File

@ -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

View File

@ -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
}

View File

@ -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)
}

View File

@ -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
}
}