feat(mdu): 增加M拓展
This commit is contained in:
parent
bda65bef5b
commit
5f75a0ac89
|
@ -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模式
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
||||
signedMul.A := io.src1
|
||||
signedMul.B := io.src2
|
||||
io.ready := cnt >= config.mulClockNum.U
|
||||
io.result := signedMul.P(64 - 1, 0)
|
||||
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
|
||||
}
|
||||
io.result := Mux(io.signed, signed, unsigned)
|
||||
io.result := signed
|
||||
io.ready := cnt >= config.mulClockNum.U
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue