commit
a26cb73dfb
|
|
@ -44,3 +44,12 @@ class BranchIO extends Bundle {
|
||||||
val isTaken = Output(Bool())
|
val isTaken = Output(Bool())
|
||||||
val target = Output(UInt(32.W))
|
val target = Output(UInt(32.W))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class FunctionUnitIO extends Bundle with HasDecodeConst {
|
||||||
|
val in = Flipped(Decoupled(new Bundle {
|
||||||
|
val src1 = Output(UInt(32.W))
|
||||||
|
val src2 = Output(UInt(32.W))
|
||||||
|
val func = Output(UInt(FuOpTypeWidth))
|
||||||
|
}))
|
||||||
|
val out = Decoupled(Output(UInt(32.W)))
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,36 +28,45 @@ class EXU extends Module with HasFuType {
|
||||||
|
|
||||||
val (src1, src2, fuType, fuOpType) = (io.in.bits.data.src1, io.in.bits.data.src2,
|
val (src1, src2, fuType, fuOpType) = (io.in.bits.data.src1, io.in.bits.data.src2,
|
||||||
io.in.bits.ctrl.fuType, io.in.bits.ctrl.fuOpType)
|
io.in.bits.ctrl.fuType, io.in.bits.ctrl.fuOpType)
|
||||||
val aluOut = (new ALU).access(src1 = src1, src2 = src2, func = fuOpType)
|
|
||||||
|
|
||||||
val bruOut = (new BRU).access(isBru = fuType === FuBru, pc = io.in.bits.pc, offset = src2,
|
val alu = Module(new ALU)
|
||||||
src1 = src1, src2 = io.in.bits.data.dest, func = fuOpType)
|
val aluOut = alu.access(valid = (fuType === FuAlu), src1 = src1, src2 = src2, func = fuOpType)
|
||||||
|
alu.io.out.ready := true.B
|
||||||
|
|
||||||
val lsu = new LSU
|
val bru = Module(new BRU)
|
||||||
val (dmem, lsuResultValid) = lsu.access(isLsu = fuType === FuLsu, base = src1, offset = src2,
|
val bruOut = bru.access(valid = (fuType === FuBru), src1 = src1, src2 = io.in.bits.data.dest, func = fuOpType)
|
||||||
func = fuOpType, wdata = io.in.bits.data.dest)
|
bru.io.pc := io.in.bits.pc
|
||||||
io.dmem <> dmem
|
bru.io.offset := src2
|
||||||
|
bru.io.out.ready := true.B
|
||||||
|
|
||||||
val mduOut = (new MDU).access(src1 = src1, src2 = src2, func = fuOpType)
|
val lsu = Module(new LSU)
|
||||||
|
val lsuOut = lsu.access(valid = (fuType === FuLsu), src1 = src1, src2 = src2, func = fuOpType)
|
||||||
|
lsu.io.wdata := io.in.bits.data.dest
|
||||||
|
io.dmem <> lsu.io.dmem
|
||||||
|
lsu.io.out.ready := true.B
|
||||||
|
|
||||||
val csr = new CSR
|
val mdu = Module(new MDU)
|
||||||
val csrOut = csr.access(isCsr = fuType === FuCsr, addr = src2(11, 0), src = src1, cmd = fuOpType)
|
val mduOut = mdu.access(valid = (fuType === FuMdu), src1 = src1, src2 = src2, func = fuOpType)
|
||||||
val isException = (io.in.bits.ctrl.isInvOpcode)
|
mdu.io.out.ready := true.B
|
||||||
val exceptionNO = Mux(io.in.bits.ctrl.isInvOpcode, 2.U, 0.U)
|
|
||||||
val exceptionJmp = csr.jmp(isCsr = fuType === FuCsr, addr = src2(11, 0),
|
val csr = Module(new CSR)
|
||||||
pc = io.in.bits.pc, cmd = fuOpType, isException = isException, exceptionNO = exceptionNO)
|
val csrOut = csr.access(valid = (fuType === FuCsr), src1 = src1, src2 = src2, func = fuOpType)
|
||||||
|
csr.io.pc := io.in.bits.pc
|
||||||
|
csr.io.isException := (io.in.bits.ctrl.isInvOpcode)
|
||||||
|
csr.io.exceptionNO := Mux(io.in.bits.ctrl.isInvOpcode, 2.U, 0.U)
|
||||||
|
csr.io.out.ready := true.B
|
||||||
|
|
||||||
io.out.bits.data := DontCare
|
io.out.bits.data := DontCare
|
||||||
io.out.bits.data.dest := LookupTree(fuType, 0.U, List(
|
io.out.bits.data.dest := LookupTree(fuType, 0.U, List(
|
||||||
FuAlu -> aluOut,
|
FuAlu -> aluOut,
|
||||||
FuBru -> (io.in.bits.pc + 4.U),
|
FuBru -> bruOut,
|
||||||
FuLsu -> lsu.rdataExt(io.dmem.r.bits.data, io.dmem.a.bits.addr, fuOpType),
|
FuLsu -> lsuOut,
|
||||||
FuCsr -> csrOut,
|
FuCsr -> csrOut,
|
||||||
FuMdu -> mduOut
|
FuMdu -> mduOut
|
||||||
))
|
))
|
||||||
|
|
||||||
when (exceptionJmp.isTaken) { io.br <> exceptionJmp }
|
when (csr.io.csrjmp.isTaken) { io.br <> csr.io.csrjmp }
|
||||||
.otherwise { io.br <> bruOut }
|
.otherwise { io.br <> bru.io.branch }
|
||||||
|
|
||||||
io.out.bits.ctrl := DontCare
|
io.out.bits.ctrl := DontCare
|
||||||
(io.out.bits.ctrl, io.in.bits.ctrl) match { case (o, i) =>
|
(io.out.bits.ctrl, io.in.bits.ctrl) match { case (o, i) =>
|
||||||
|
|
@ -65,7 +74,7 @@ class EXU extends Module with HasFuType {
|
||||||
o.rfDest := i.rfDest
|
o.rfDest := i.rfDest
|
||||||
}
|
}
|
||||||
io.out.bits.pc := io.in.bits.pc
|
io.out.bits.pc := io.in.bits.pc
|
||||||
io.out.valid := io.in.valid && ((fuType =/= FuLsu) || lsuResultValid)
|
io.out.valid := io.in.valid && ((fuType =/= FuLsu) || lsu.io.out.valid)
|
||||||
|
|
||||||
csr.instrCnt(io.csrCtrl.instrCommit)
|
csr.io.instrCommit := io.csrCtrl.instrCommit
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,10 +71,20 @@ object ALUInstr extends HasDecodeConst {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
class ALU extends HasALUOpType {
|
class ALU extends Module with HasALUOpType {
|
||||||
def access(src1: UInt, src2: UInt, func: UInt): UInt = {
|
val io = IO(new FunctionUnitIO)
|
||||||
|
|
||||||
|
val (valid, src1, src2, func) = (io.in.valid, io.in.bits.src1, io.in.bits.src2, io.in.bits.func)
|
||||||
|
def access(valid: Bool, src1: UInt, src2: UInt, func: UInt): UInt = {
|
||||||
|
this.valid := valid
|
||||||
|
this.src1 := src1
|
||||||
|
this.src2 := src2
|
||||||
|
this.func := func
|
||||||
|
io.out.bits
|
||||||
|
}
|
||||||
|
|
||||||
val shamt = src2(4, 0)
|
val shamt = src2(4, 0)
|
||||||
LookupTree(func, 0.U, List(
|
io.out.bits := LookupTree(func, 0.U, List(
|
||||||
AluAdd -> (src1 + src2),
|
AluAdd -> (src1 + src2),
|
||||||
AluSll -> ((src1 << shamt)(31, 0)),
|
AluSll -> ((src1 << shamt)(31, 0)),
|
||||||
AluSlt -> ((src1.asSInt < src2.asSInt).asUInt),
|
AluSlt -> ((src1.asSInt < src2.asSInt).asUInt),
|
||||||
|
|
@ -87,5 +97,7 @@ class ALU extends HasALUOpType {
|
||||||
AluLui -> src2,
|
AluLui -> src2,
|
||||||
AluSra -> ((src1.asSInt >> shamt).asUInt)
|
AluSra -> ((src1.asSInt >> shamt).asUInt)
|
||||||
))
|
))
|
||||||
}
|
|
||||||
|
io.in.ready := true.B
|
||||||
|
io.out.valid := valid
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,11 +40,26 @@ object BRUInstr extends HasDecodeConst {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
class BRU extends HasBRUOpType {
|
class BRUIO extends FunctionUnitIO {
|
||||||
def access(isBru: Bool, pc: UInt, offset: UInt, src1: UInt, src2: UInt, func: UInt): BranchIO = {
|
val pc = Input(UInt(32.W))
|
||||||
val branch = Wire(new BranchIO)
|
val offset = Input(UInt(32.W))
|
||||||
branch.target := Mux(func === BruJalr, src1 + offset, pc + offset)
|
val branch = new BranchIO
|
||||||
branch.isTaken := isBru && LookupTree(func, false.B, List(
|
}
|
||||||
|
|
||||||
|
class BRU extends Module with HasBRUOpType {
|
||||||
|
val io = IO(new BRUIO)
|
||||||
|
|
||||||
|
val (valid, src1, src2, func) = (io.in.valid, io.in.bits.src1, io.in.bits.src2, io.in.bits.func)
|
||||||
|
def access(valid: Bool, src1: UInt, src2: UInt, func: UInt): UInt = {
|
||||||
|
this.valid := valid
|
||||||
|
this.src1 := src1
|
||||||
|
this.src2 := src2
|
||||||
|
this.func := func
|
||||||
|
io.out.bits
|
||||||
|
}
|
||||||
|
|
||||||
|
io.branch.target := Mux(func === BruJalr, src1, io.pc) + io.offset
|
||||||
|
io.branch.isTaken := valid && LookupTree(func, false.B, List(
|
||||||
BruBeq -> (src1 === src2),
|
BruBeq -> (src1 === src2),
|
||||||
BruBne -> (src1 =/= src2),
|
BruBne -> (src1 =/= src2),
|
||||||
BruBlt -> (src1.asSInt < src2.asSInt),
|
BruBlt -> (src1.asSInt < src2.asSInt),
|
||||||
|
|
@ -54,6 +69,8 @@ class BRU extends HasBRUOpType {
|
||||||
BruJal -> true.B,
|
BruJal -> true.B,
|
||||||
BruJalr -> true.B
|
BruJalr -> true.B
|
||||||
))
|
))
|
||||||
branch
|
io.out.bits := io.pc + 4.U
|
||||||
}
|
|
||||||
|
io.in.ready := true.B
|
||||||
|
io.out.valid := valid
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,26 @@ trait HasCSRConst {
|
||||||
def privMret = 0x302.U
|
def privMret = 0x302.U
|
||||||
}
|
}
|
||||||
|
|
||||||
class CSR extends HasCSROpType with HasCSRConst {
|
class CSRIO extends FunctionUnitIO {
|
||||||
|
val pc = Input(UInt(32.W))
|
||||||
|
val isException = Input(Bool())
|
||||||
|
val exceptionNO = Input(UInt(4.W))
|
||||||
|
val csrjmp = new BranchIO
|
||||||
|
val instrCommit = Input(Bool())
|
||||||
|
}
|
||||||
|
|
||||||
|
class CSR extends Module with HasCSROpType with HasCSRConst {
|
||||||
|
val io = IO(new CSRIO)
|
||||||
|
|
||||||
|
val (valid, src1, src2, func) = (io.in.valid, io.in.bits.src1, io.in.bits.src2, io.in.bits.func)
|
||||||
|
def access(valid: Bool, src1: UInt, src2: UInt, func: UInt): UInt = {
|
||||||
|
this.valid := valid
|
||||||
|
this.src1 := src1
|
||||||
|
this.src2 := src2
|
||||||
|
this.func := func
|
||||||
|
io.out.bits
|
||||||
|
}
|
||||||
|
|
||||||
val mtvec = Reg(UInt(32.W))
|
val mtvec = Reg(UInt(32.W))
|
||||||
val mcause = Reg(UInt(32.W))
|
val mcause = Reg(UInt(32.W))
|
||||||
val mstatus = Reg(UInt(32.W))
|
val mstatus = Reg(UInt(32.W))
|
||||||
|
|
@ -67,44 +86,38 @@ class CSR extends HasCSROpType with HasCSRConst {
|
||||||
scalaMapping.filter { case (x, y) => x == addr } (0)._2
|
scalaMapping.filter { case (x, y) => x == addr } (0)._2
|
||||||
}
|
}
|
||||||
|
|
||||||
def access(isCsr: Bool, addr: UInt, src: UInt, cmd: UInt): UInt = {
|
val addr = src2(11, 0)
|
||||||
val rdata = LookupTree(addr, 0.U, chiselMapping)
|
val rdata = LookupTree(addr, 0.U, chiselMapping)
|
||||||
val wdata = LookupTree(cmd, 0.U, List(
|
val wdata = LookupTree(func, 0.U, List(
|
||||||
CsrWrt -> src,
|
CsrWrt -> src1,
|
||||||
CsrSet -> (rdata | src),
|
CsrSet -> (rdata | src1),
|
||||||
CsrClr -> (rdata & ~src)
|
CsrClr -> (rdata & ~src1)
|
||||||
))
|
))
|
||||||
|
|
||||||
when (isCsr && cmd =/= CsrJmp) {
|
when (valid && func =/= CsrJmp) {
|
||||||
when (addr === Mtvec.U) { mtvec := wdata }
|
when (addr === Mtvec.U) { mtvec := wdata }
|
||||||
when (addr === Mstatus.U) { mstatus := wdata }
|
when (addr === Mstatus.U) { mstatus := wdata }
|
||||||
when (addr === Mepc.U) { mepc := wdata }
|
when (addr === Mepc.U) { mepc := wdata }
|
||||||
when (addr === Mcause.U) { mcause := wdata }
|
when (addr === Mcause.U) { mcause := wdata }
|
||||||
}
|
}
|
||||||
|
|
||||||
rdata
|
io.out.bits := rdata
|
||||||
}
|
|
||||||
|
|
||||||
def jmp(isCsr: Bool, addr: UInt, pc: UInt, cmd: UInt, isException: Bool, exceptionNO: UInt): BranchIO = {
|
io.csrjmp.isTaken := valid && func === CsrJmp
|
||||||
val csrjmp = Wire(new BranchIO)
|
io.csrjmp.target := LookupTree(addr, 0.U, List(
|
||||||
csrjmp.isTaken := isCsr && cmd === CsrJmp
|
|
||||||
csrjmp.target := LookupTree(addr, 0.U, List(
|
|
||||||
privEcall -> mtvec,
|
privEcall -> mtvec,
|
||||||
privMret -> mepc
|
privMret -> mepc
|
||||||
))
|
))
|
||||||
|
|
||||||
val isEcall = (addr === privEcall)
|
val isEcall = (addr === privEcall)
|
||||||
when (csrjmp.isTaken && (isEcall || isException)) {
|
when (io.csrjmp.isTaken && (isEcall || io.isException)) {
|
||||||
mepc := pc
|
mepc := io.pc
|
||||||
mcause := Mux(isException, exceptionNO, 11.U)
|
mcause := Mux(io.isException, io.exceptionNO, 11.U)
|
||||||
}
|
|
||||||
csrjmp
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mcycle := mcycle + 1.U
|
mcycle := mcycle + 1.U
|
||||||
def instrCnt(instrCommit: Bool) {
|
when (io.instrCommit) { minstret := minstret + 1.U }
|
||||||
when (instrCommit) {
|
|
||||||
minstret := minstret + 1.U
|
io.in.ready := true.B
|
||||||
}
|
io.out.valid := valid
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,23 @@ object LSUInstr extends HasDecodeConst {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
class LSU extends HasLSUOpType {
|
class LSUIO extends FunctionUnitIO {
|
||||||
|
val wdata = Input(UInt(32.W))
|
||||||
|
val dmem = new MemIO
|
||||||
|
}
|
||||||
|
|
||||||
|
class LSU extends Module with HasLSUOpType {
|
||||||
|
val io = IO(new LSUIO)
|
||||||
|
|
||||||
|
val (valid, src1, src2, func) = (io.in.valid, io.in.bits.src1, io.in.bits.src2, io.in.bits.func)
|
||||||
|
def access(valid: Bool, src1: UInt, src2: UInt, func: UInt): UInt = {
|
||||||
|
this.valid := valid
|
||||||
|
this.src1 := src1
|
||||||
|
this.src2 := src2
|
||||||
|
this.func := func
|
||||||
|
io.out.bits
|
||||||
|
}
|
||||||
|
|
||||||
def genWmask(addr: UInt, sizeEncode: UInt): UInt = {
|
def genWmask(addr: UInt, sizeEncode: UInt): UInt = {
|
||||||
LookupTree(sizeEncode, List(
|
LookupTree(sizeEncode, List(
|
||||||
"b00".U -> 0x1.U,
|
"b00".U -> 0x1.U,
|
||||||
|
|
@ -55,8 +71,10 @@ class LSU extends HasLSUOpType {
|
||||||
"b10".U -> data
|
"b10".U -> data
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
def access(isLsu: Bool, base: UInt, offset: UInt, func: UInt, wdata: UInt): (MemIO, Bool) = {
|
|
||||||
val dmem = Wire(new MemIO)
|
val dmem = io.dmem
|
||||||
|
val addr = src1 + src2
|
||||||
|
|
||||||
val s_idle :: s_wait_resp :: Nil = Enum(2)
|
val s_idle :: s_wait_resp :: Nil = Enum(2)
|
||||||
val state = RegInit(s_idle)
|
val state = RegInit(s_idle)
|
||||||
|
|
||||||
|
|
@ -70,29 +88,29 @@ class LSU extends HasLSUOpType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dmem.a.bits.addr := base + offset
|
dmem.a.bits.addr := addr
|
||||||
dmem.a.bits.size := func(1, 0)
|
dmem.a.bits.size := func(1, 0)
|
||||||
dmem.a.valid := isLsu && (state === s_idle)
|
dmem.a.valid := valid && (state === s_idle)
|
||||||
dmem.w.valid := isLsu && func(3)
|
dmem.w.valid := valid && func(3)
|
||||||
dmem.w.bits.data := genWdata(wdata, func(1, 0))
|
dmem.w.bits.data := genWdata(io.wdata, func(1, 0))
|
||||||
dmem.w.bits.mask := genWmask(base + offset, func(1, 0))
|
dmem.w.bits.mask := genWmask(addr, func(1, 0))
|
||||||
dmem.r.ready := true.B
|
dmem.r.ready := true.B
|
||||||
|
|
||||||
(dmem, Mux(dmem.w.valid, dmem.a.fire(), dmem.r.fire()))
|
io.out.valid := Mux(dmem.w.valid, dmem.a.fire(), dmem.r.fire())
|
||||||
}
|
io.in.ready := (state === s_idle)
|
||||||
def rdataExt(rdataFromBus: UInt, addr: UInt, func: UInt): UInt = {
|
|
||||||
|
val rdataFromBus = io.dmem.r.bits.data
|
||||||
val rdata = LookupTree(addr(1, 0), List(
|
val rdata = LookupTree(addr(1, 0), List(
|
||||||
"b00".U -> rdataFromBus,
|
"b00".U -> rdataFromBus,
|
||||||
"b01".U -> rdataFromBus(15, 8),
|
"b01".U -> rdataFromBus(15, 8),
|
||||||
"b10".U -> rdataFromBus(31, 16),
|
"b10".U -> rdataFromBus(31, 16),
|
||||||
"b11".U -> rdataFromBus(31, 24)
|
"b11".U -> rdataFromBus(31, 24)
|
||||||
))
|
))
|
||||||
LookupTree(func, List(
|
io.out.bits := LookupTree(func, List(
|
||||||
LsuLb -> Cat(Fill(24, rdata(7)), rdata(7, 0)),
|
LsuLb -> Cat(Fill(24, rdata(7)), rdata(7, 0)),
|
||||||
LsuLh -> Cat(Fill(16, rdata(15)), rdata(15, 0)),
|
LsuLh -> Cat(Fill(16, rdata(15)), rdata(15, 0)),
|
||||||
LsuLw -> rdata,
|
LsuLw -> rdata,
|
||||||
LsuLbu -> Cat(0.U(24.W), rdata(7, 0)),
|
LsuLbu -> Cat(0.U(24.W), rdata(7, 0)),
|
||||||
LsuLhu -> Cat(0.U(16.W), rdata(15, 0))
|
LsuLhu -> Cat(0.U(16.W), rdata(15, 0))
|
||||||
))
|
))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,12 +32,20 @@ object MDUInstr extends HasDecodeConst {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
class MDU extends HasMDUOpType {
|
class MDU extends Module with HasMDUOpType {
|
||||||
def access(src1: UInt, src2: UInt, func: UInt): UInt = {
|
val io = IO(new FunctionUnitIO)
|
||||||
0.U
|
|
||||||
/*
|
val (valid, src1, src2, func) = (io.in.valid, io.in.bits.src1, io.in.bits.src2, io.in.bits.func)
|
||||||
|
def access(valid: Bool, src1: UInt, src2: UInt, func: UInt): UInt = {
|
||||||
|
this.valid := valid
|
||||||
|
this.src1 := src1
|
||||||
|
this.src2 := src2
|
||||||
|
this.func := func
|
||||||
|
io.out.bits
|
||||||
|
}
|
||||||
|
|
||||||
val mulRes = (src1.asSInt * src2.asSInt).asUInt
|
val mulRes = (src1.asSInt * src2.asSInt).asUInt
|
||||||
LookupTree(func, 0.U, List(
|
io.out.bits := LookupTree(func, 0.U, List(
|
||||||
MduMul -> mulRes(31, 0),
|
MduMul -> mulRes(31, 0),
|
||||||
MduMulh -> mulRes(63, 32),
|
MduMulh -> mulRes(63, 32),
|
||||||
MduDiv -> (src1.asSInt / src2.asSInt).asUInt,
|
MduDiv -> (src1.asSInt / src2.asSInt).asUInt,
|
||||||
|
|
@ -45,6 +53,7 @@ class MDU extends HasMDUOpType {
|
||||||
MduRem -> (src1.asSInt % src2.asSInt).asUInt,
|
MduRem -> (src1.asSInt % src2.asSInt).asUInt,
|
||||||
MduRemu -> (src1 % src2)
|
MduRemu -> (src1 % src2)
|
||||||
))
|
))
|
||||||
*/
|
|
||||||
}
|
io.in.ready := true.B
|
||||||
|
io.out.valid := valid
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue