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 build: Boolean = false, // 是否为build模式
|
||||||
// 指令集
|
// 指令集
|
||||||
val isRV32: Boolean = false, // 是否为RV32
|
val isRV32: Boolean = false, // 是否为RV32
|
||||||
val hasMExtension: Boolean = false, // 是否有乘除法单元
|
val hasMExtension: Boolean = true, // 是否有乘除法单元
|
||||||
// 特权模式
|
// 特权模式
|
||||||
val hasSMode: Boolean = false, // 是否有S模式
|
val hasSMode: Boolean = false, // 是否有S模式
|
||||||
val hasUMode: Boolean = false, // 是否有U模式
|
val hasUMode: Boolean = false, // 是否有U模式
|
||||||
|
|
|
@ -21,7 +21,7 @@ class Decoder extends Module with HasInstrType {
|
||||||
val instrType :: fuType :: fuOpType :: Nil =
|
val instrType :: fuType :: fuOpType :: Nil =
|
||||||
ListLookup(inst, Instructions.DecodeDefault, Instructions.DecodeTable)
|
ListLookup(inst, Instructions.DecodeDefault, Instructions.DecodeTable)
|
||||||
|
|
||||||
val SrcTypeTable = Seq(
|
val srcTypeTable = Seq(
|
||||||
InstrI -> (SrcType.reg, SrcType.imm),
|
InstrI -> (SrcType.reg, SrcType.imm),
|
||||||
InstrR -> (SrcType.reg, SrcType.reg),
|
InstrR -> (SrcType.reg, SrcType.reg),
|
||||||
InstrS -> (SrcType.reg, SrcType.reg),
|
InstrS -> (SrcType.reg, SrcType.reg),
|
||||||
|
@ -31,8 +31,8 @@ class Decoder extends Module with HasInstrType {
|
||||||
InstrJ -> (SrcType.pc, SrcType.imm),
|
InstrJ -> (SrcType.pc, SrcType.imm),
|
||||||
InstrN -> (SrcType.pc, SrcType.imm)
|
InstrN -> (SrcType.pc, SrcType.imm)
|
||||||
)
|
)
|
||||||
val src1Type = LookupTree(instrType, SrcTypeTable.map(p => (p._1, p._2._1)))
|
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 src2Type = LookupTree(instrType, srcTypeTable.map(p => (p._1, p._2._2)))
|
||||||
|
|
||||||
val (rs, rt, rd) = (inst(19, 15), inst(24, 20), inst(11, 7))
|
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.reg2_raddr := Mux(io.out.info.reg2_ren, rt, 0.U)
|
||||||
io.out.info.fusel := fuType
|
io.out.info.fusel := fuType
|
||||||
io.out.info.op := fuOpType
|
io.out.info.op := fuOpType
|
||||||
io.out.info.reg_wen := isrfWen(instrType)
|
io.out.info.reg_wen := isrfWen(instrType)
|
||||||
io.out.info.reg_waddr := Mux(isrfWen(instrType), rd, 0.U)
|
io.out.info.reg_waddr := Mux(isrfWen(instrType), rd, 0.U)
|
||||||
io.out.info.imm := LookupTree(
|
io.out.info.imm := LookupTree(
|
||||||
instrType,
|
instrType,
|
||||||
Seq(
|
Seq(
|
||||||
|
|
|
@ -12,14 +12,14 @@ class SignedDiv extends BlackBox with HasBlackBoxResource {
|
||||||
// 除数
|
// 除数
|
||||||
val s_axis_divisor_tvalid = Input(Bool())
|
val s_axis_divisor_tvalid = Input(Bool())
|
||||||
val s_axis_divisor_tready = Output(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_tvalid = Input(Bool())
|
||||||
val s_axis_dividend_tready = Output(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_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_tvalid = Input(Bool())
|
||||||
val s_axis_divisor_tready = Output(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_tvalid = Input(Bool())
|
||||||
val s_axis_dividend_tready = Output(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_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 {
|
class Div(implicit config: CpuConfig) extends Module {
|
||||||
val io = IO(new Bundle {
|
val io = IO(new Bundle {
|
||||||
val src1 = Input(UInt(DATA_WID.W))
|
val src1 = Input(UInt(XLEN.W))
|
||||||
val src2 = Input(UInt(DATA_WID.W))
|
val src2 = Input(UInt(XLEN.W))
|
||||||
val signed = Input(Bool())
|
val signed = Input(Bool())
|
||||||
val start = Input(Bool())
|
val start = Input(Bool())
|
||||||
val allow_to_go = Input(Bool())
|
val allow_to_go = Input(Bool())
|
||||||
|
|
||||||
val ready = Output(Bool())
|
val ready = Output(Bool())
|
||||||
val result = Output(UInt(64.W))
|
val result = Output(UInt((2 * XLEN).W))
|
||||||
})
|
})
|
||||||
|
|
||||||
if (config.build) {
|
if (config.build) {
|
||||||
|
@ -118,9 +118,9 @@ class Div(implicit config: CpuConfig) extends Module {
|
||||||
unsignedDiv.m_axis_dout_tvalid || unsignedDiv_done
|
unsignedDiv.m_axis_dout_tvalid || unsignedDiv_done
|
||||||
)
|
)
|
||||||
val signedRes =
|
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 =
|
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)
|
io.result := Mux(io.signed, signedRes, unsignedRes)
|
||||||
} else {
|
} else {
|
||||||
val cnt = RegInit(0.U(log2Ceil(config.divClockNum + 1).W))
|
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 div_signed = io.signed
|
||||||
|
|
||||||
val dividend_signed = io.src1(31) & div_signed
|
val dividend_signed = io.src1(XLEN - 1) & div_signed
|
||||||
val divisor_signed = io.src2(31) & div_signed
|
val divisor_signed = io.src2(XLEN - 1) & div_signed
|
||||||
|
|
||||||
val dividend_abs = Mux(dividend_signed, (-io.src1).asUInt, io.src1.asUInt)
|
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 divisor_abs = Mux(divisor_signed, (-io.src2).asUInt, io.src2.asUInt)
|
||||||
|
|
||||||
val quotient_signed = (io.src1(31) ^ io.src2(31)) & div_signed
|
val quotient_signed = (io.src1(XLEN - 1) ^ io.src2(XLEN - 1)) & div_signed
|
||||||
val remainder_signed = io.src1(31) & div_signed
|
val remainder_signed = io.src1(XLEN - 1) & div_signed
|
||||||
|
|
||||||
val quotient_abs = dividend_abs / divisor_abs
|
val quotient_abs = dividend_abs / divisor_abs
|
||||||
val remainder_abs = dividend_abs - quotient_abs * divisor_abs
|
val remainder_abs = dividend_abs - quotient_abs * divisor_abs
|
||||||
|
|
||||||
val quotient = RegInit(0.S(32.W))
|
val quotient = RegInit(0.S(XLEN.W))
|
||||||
val remainder = RegInit(0.S(32.W))
|
val remainder = RegInit(0.S(XLEN.W))
|
||||||
|
|
||||||
when(io.start) {
|
when(io.start) {
|
||||||
quotient := Mux(quotient_signed, (-quotient_abs).asSInt, quotient_abs.asSInt)
|
quotient := Mux(quotient_signed, (-quotient_abs).asSInt, quotient_abs.asSInt)
|
||||||
remainder := Mux(remainder_signed, (-remainder_abs).asSInt, remainder_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
|
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 alu = Seq.fill(config.decoderNum)(Module(new Alu()))
|
||||||
val branchCtrl = Module(new BranchCtrl()).io
|
val branchCtrl = Module(new BranchCtrl()).io
|
||||||
val mou = Module(new Mou()).io
|
val mou = Module(new Mou()).io
|
||||||
|
val mdu = Module(new Mdu()).io
|
||||||
|
|
||||||
mou.in.info := io.inst(0).info
|
mou.in.info := io.inst(0).info
|
||||||
mou.in.pc := io.inst(0).pc
|
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)
|
io.branch.target := Mux(branchCtrl_flush, branchCtrl.out.target, mou.out.target)
|
||||||
|
|
||||||
for (i <- 0 until (config.fuNum)) {
|
for (i <- 0 until (config.fuNum)) {
|
||||||
alu(i).io.info := io.inst(i).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 := io.inst(i).src_info
|
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(
|
io.inst(0).result.alu := Mux(
|
||||||
ALUOpType.isBru(io.inst(0).info.op),
|
ALUOpType.isBru(io.inst(0).info.op),
|
||||||
io.inst(0).pc + 4.U,
|
io.inst(0).pc + 4.U,
|
||||||
alu(0).io.result
|
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.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 io = IO(new Bundle {
|
||||||
val CLK = Input(Clock())
|
val CLK = Input(Clock())
|
||||||
val CE = Input(Bool())
|
val CE = Input(Bool())
|
||||||
val A = Input(UInt((DATA_WID + 1).W))
|
val A = Input(UInt((XLEN + 1).W))
|
||||||
val B = Input(UInt((DATA_WID + 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 {
|
class Mul(implicit val config: CpuConfig) extends Module {
|
||||||
val io = IO(new Bundle {
|
val io = IO(new Bundle {
|
||||||
val src1 = Input(UInt(DATA_WID.W))
|
val src1 = Input(UInt((XLEN + 1).W))
|
||||||
val src2 = Input(UInt(DATA_WID.W))
|
val src2 = Input(UInt((XLEN + 1).W))
|
||||||
val signed = Input(Bool())
|
|
||||||
val start = Input(Bool())
|
val start = Input(Bool())
|
||||||
val allow_to_go = Input(Bool())
|
val allow_to_go = Input(Bool())
|
||||||
|
|
||||||
val ready = Output(Bool())
|
val ready = Output(Bool())
|
||||||
val result = Output(UInt(64.W))
|
val result = Output(UInt((2 * XLEN).W))
|
||||||
})
|
})
|
||||||
|
|
||||||
if (config.build) {
|
if (config.build) {
|
||||||
|
@ -43,15 +42,11 @@ class Mul(implicit val config: CpuConfig) extends Module {
|
||||||
|
|
||||||
signedMul.CLK := clock
|
signedMul.CLK := clock
|
||||||
signedMul.CE := io.start
|
signedMul.CE := io.start
|
||||||
when(io.signed) {
|
|
||||||
signedMul.A := Cat(io.src1(DATA_WID - 1), io.src1)
|
signedMul.A := io.src1
|
||||||
signedMul.B := Cat(io.src2(DATA_WID - 1), io.src2)
|
signedMul.B := io.src2
|
||||||
}.otherwise {
|
io.ready := cnt >= config.mulClockNum.U
|
||||||
signedMul.A := Cat(0.U(1.W), io.src1)
|
io.result := signedMul.P((2 * XLEN) - 1, 0)
|
||||||
signedMul.B := Cat(0.U(1.W), io.src2)
|
|
||||||
}
|
|
||||||
io.ready := cnt >= config.mulClockNum.U
|
|
||||||
io.result := signedMul.P(64 - 1, 0)
|
|
||||||
} else {
|
} else {
|
||||||
val cnt = RegInit(0.U(log2Ceil(config.mulClockNum + 1).W))
|
val cnt = RegInit(0.U(log2Ceil(config.mulClockNum + 1).W))
|
||||||
cnt := MuxCase(
|
cnt := MuxCase(
|
||||||
|
@ -62,13 +57,11 @@ class Mul(implicit val config: CpuConfig) extends Module {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
val signed = RegInit(0.U(64.W))
|
val signed = RegInit(0.U((2 * XLEN).W))
|
||||||
val unsigned = RegInit(0.U(64.W))
|
|
||||||
when(io.start) {
|
when(io.start) {
|
||||||
signed := (io.src1.asSInt * io.src2.asSInt).asUInt
|
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
|
io.ready := cnt >= config.mulClockNum.U
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue