Merge pull request #13 from sashimi-yzh/refactor-exu

Refactor exu
This commit is contained in:
Zihao Yu 2019-02-23 18:33:01 +08:00 committed by GitHub
commit a26cb73dfb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 218 additions and 131 deletions

View File

@ -44,3 +44,12 @@ class BranchIO extends Bundle {
val isTaken = Output(Bool())
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)))
}

View File

@ -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,
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,
src1 = src1, src2 = io.in.bits.data.dest, func = fuOpType)
val alu = Module(new ALU)
val aluOut = alu.access(valid = (fuType === FuAlu), src1 = src1, src2 = src2, func = fuOpType)
alu.io.out.ready := true.B
val lsu = new LSU
val (dmem, lsuResultValid) = lsu.access(isLsu = fuType === FuLsu, base = src1, offset = src2,
func = fuOpType, wdata = io.in.bits.data.dest)
io.dmem <> dmem
val bru = Module(new BRU)
val bruOut = bru.access(valid = (fuType === FuBru), src1 = src1, src2 = io.in.bits.data.dest, func = fuOpType)
bru.io.pc := io.in.bits.pc
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 csrOut = csr.access(isCsr = fuType === FuCsr, addr = src2(11, 0), src = src1, cmd = fuOpType)
val isException = (io.in.bits.ctrl.isInvOpcode)
val exceptionNO = Mux(io.in.bits.ctrl.isInvOpcode, 2.U, 0.U)
val exceptionJmp = csr.jmp(isCsr = fuType === FuCsr, addr = src2(11, 0),
pc = io.in.bits.pc, cmd = fuOpType, isException = isException, exceptionNO = exceptionNO)
val mdu = Module(new MDU)
val mduOut = mdu.access(valid = (fuType === FuMdu), src1 = src1, src2 = src2, func = fuOpType)
mdu.io.out.ready := true.B
val csr = Module(new CSR)
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.dest := LookupTree(fuType, 0.U, List(
FuAlu -> aluOut,
FuBru -> (io.in.bits.pc + 4.U),
FuLsu -> lsu.rdataExt(io.dmem.r.bits.data, io.dmem.a.bits.addr, fuOpType),
FuBru -> bruOut,
FuLsu -> lsuOut,
FuCsr -> csrOut,
FuMdu -> mduOut
))
when (exceptionJmp.isTaken) { io.br <> exceptionJmp }
.otherwise { io.br <> bruOut }
when (csr.io.csrjmp.isTaken) { io.br <> csr.io.csrjmp }
.otherwise { io.br <> bru.io.branch }
io.out.bits.ctrl := DontCare
(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
}
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
}

View File

@ -71,21 +71,33 @@ object ALUInstr extends HasDecodeConst {
)
}
class ALU extends HasALUOpType {
def access(src1: UInt, src2: UInt, func: UInt): UInt = {
val shamt = src2(4, 0)
LookupTree(func, 0.U, List(
AluAdd -> (src1 + src2),
AluSll -> ((src1 << shamt)(31, 0)),
AluSlt -> ((src1.asSInt < src2.asSInt).asUInt),
AluSltu -> ((src1 < src2).asUInt),
AluXor -> (src1 ^ src2),
AluSrl -> (src1 >> shamt),
AluOr -> (src1 | src2),
AluAnd -> (src1 & src2),
AluSub -> (src1 - src2),
AluLui -> src2,
AluSra -> ((src1.asSInt >> shamt).asUInt)
))
class ALU extends Module with HasALUOpType {
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)
io.out.bits := LookupTree(func, 0.U, List(
AluAdd -> (src1 + src2),
AluSll -> ((src1 << shamt)(31, 0)),
AluSlt -> ((src1.asSInt < src2.asSInt).asUInt),
AluSltu -> ((src1 < src2).asUInt),
AluXor -> (src1 ^ src2),
AluSrl -> (src1 >> shamt),
AluOr -> (src1 | src2),
AluAnd -> (src1 & src2),
AluSub -> (src1 - src2),
AluLui -> src2,
AluSra -> ((src1.asSInt >> shamt).asUInt)
))
io.in.ready := true.B
io.out.valid := valid
}

View File

@ -40,20 +40,37 @@ object BRUInstr extends HasDecodeConst {
)
}
class BRU extends HasBRUOpType {
def access(isBru: Bool, pc: UInt, offset: UInt, src1: UInt, src2: UInt, func: UInt): BranchIO = {
val branch = Wire(new BranchIO)
branch.target := Mux(func === BruJalr, src1 + offset, pc + offset)
branch.isTaken := isBru && LookupTree(func, false.B, List(
BruBeq -> (src1 === src2),
BruBne -> (src1 =/= src2),
BruBlt -> (src1.asSInt < src2.asSInt),
BruBge -> (src1.asSInt >= src2.asSInt),
BruBltu -> (src1 < src2),
BruBgeu -> (src1 >= src2),
BruJal -> true.B,
BruJalr -> true.B
))
branch
}
class BRUIO extends FunctionUnitIO {
val pc = Input(UInt(32.W))
val offset = Input(UInt(32.W))
val branch = new BranchIO
}
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),
BruBne -> (src1 =/= src2),
BruBlt -> (src1.asSInt < src2.asSInt),
BruBge -> (src1.asSInt >= src2.asSInt),
BruBltu -> (src1 < src2),
BruBgeu -> (src1 >= src2),
BruJal -> true.B,
BruJalr -> true.B
))
io.out.bits := io.pc + 4.U
io.in.ready := true.B
io.out.valid := valid
}

View File

@ -41,7 +41,26 @@ trait HasCSRConst {
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 mcause = 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
}
def access(isCsr: Bool, addr: UInt, src: UInt, cmd: UInt): UInt = {
val rdata = LookupTree(addr, 0.U, chiselMapping)
val wdata = LookupTree(cmd, 0.U, List(
CsrWrt -> src,
CsrSet -> (rdata | src),
CsrClr -> (rdata & ~src)
))
val addr = src2(11, 0)
val rdata = LookupTree(addr, 0.U, chiselMapping)
val wdata = LookupTree(func, 0.U, List(
CsrWrt -> src1,
CsrSet -> (rdata | src1),
CsrClr -> (rdata & ~src1)
))
when (isCsr && cmd =/= CsrJmp) {
when (addr === Mtvec.U) { mtvec := wdata }
when (addr === Mstatus.U) { mstatus := wdata }
when (addr === Mepc.U) { mepc := wdata }
when (addr === Mcause.U) { mcause := wdata }
}
rdata
when (valid && func =/= CsrJmp) {
when (addr === Mtvec.U) { mtvec := wdata }
when (addr === Mstatus.U) { mstatus := wdata }
when (addr === Mepc.U) { mepc := wdata }
when (addr === Mcause.U) { mcause := wdata }
}
def jmp(isCsr: Bool, addr: UInt, pc: UInt, cmd: UInt, isException: Bool, exceptionNO: UInt): BranchIO = {
val csrjmp = Wire(new BranchIO)
csrjmp.isTaken := isCsr && cmd === CsrJmp
csrjmp.target := LookupTree(addr, 0.U, List(
privEcall -> mtvec,
privMret -> mepc
))
io.out.bits := rdata
val isEcall = (addr === privEcall)
when (csrjmp.isTaken && (isEcall || isException)) {
mepc := pc
mcause := Mux(isException, exceptionNO, 11.U)
}
csrjmp
io.csrjmp.isTaken := valid && func === CsrJmp
io.csrjmp.target := LookupTree(addr, 0.U, List(
privEcall -> mtvec,
privMret -> mepc
))
val isEcall = (addr === privEcall)
when (io.csrjmp.isTaken && (isEcall || io.isException)) {
mepc := io.pc
mcause := Mux(io.isException, io.exceptionNO, 11.U)
}
mcycle := mcycle + 1.U
def instrCnt(instrCommit: Bool) {
when (instrCommit) {
minstret := minstret + 1.U
}
}
when (io.instrCommit) { minstret := minstret + 1.U }
io.in.ready := true.B
io.out.valid := valid
}

View File

@ -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 = {
LookupTree(sizeEncode, List(
"b00".U -> 0x1.U,
@ -55,44 +71,46 @@ class LSU extends HasLSUOpType {
"b10".U -> data
))
}
def access(isLsu: Bool, base: UInt, offset: UInt, func: UInt, wdata: UInt): (MemIO, Bool) = {
val dmem = Wire(new MemIO)
val s_idle :: s_wait_resp :: Nil = Enum(2)
val state = RegInit(s_idle)
switch (state) {
is (s_idle) {
when (dmem.a.fire()) { state := Mux(dmem.w.valid || dmem.r.fire(), s_idle, s_wait_resp) }
}
val dmem = io.dmem
val addr = src1 + src2
is (s_wait_resp) {
when (dmem.r.fire()) { state := s_idle }
}
val s_idle :: s_wait_resp :: Nil = Enum(2)
val state = RegInit(s_idle)
switch (state) {
is (s_idle) {
when (dmem.a.fire()) { state := Mux(dmem.w.valid || dmem.r.fire(), s_idle, s_wait_resp) }
}
dmem.a.bits.addr := base + offset
dmem.a.bits.size := func(1, 0)
dmem.a.valid := isLsu && (state === s_idle)
dmem.w.valid := isLsu && func(3)
dmem.w.bits.data := genWdata(wdata, func(1, 0))
dmem.w.bits.mask := genWmask(base + offset, func(1, 0))
dmem.r.ready := true.B
(dmem, Mux(dmem.w.valid, dmem.a.fire(), dmem.r.fire()))
is (s_wait_resp) {
when (dmem.r.fire()) { state := s_idle }
}
}
def rdataExt(rdataFromBus: UInt, addr: UInt, func: UInt): UInt = {
val rdata = LookupTree(addr(1, 0), List(
"b00".U -> rdataFromBus,
"b01".U -> rdataFromBus(15, 8),
"b10".U -> rdataFromBus(31, 16),
"b11".U -> rdataFromBus(31, 24)
))
LookupTree(func, List(
dmem.a.bits.addr := addr
dmem.a.bits.size := func(1, 0)
dmem.a.valid := valid && (state === s_idle)
dmem.w.valid := valid && func(3)
dmem.w.bits.data := genWdata(io.wdata, func(1, 0))
dmem.w.bits.mask := genWmask(addr, func(1, 0))
dmem.r.ready := true.B
io.out.valid := Mux(dmem.w.valid, dmem.a.fire(), dmem.r.fire())
io.in.ready := (state === s_idle)
val rdataFromBus = io.dmem.r.bits.data
val rdata = LookupTree(addr(1, 0), List(
"b00".U -> rdataFromBus,
"b01".U -> rdataFromBus(15, 8),
"b10".U -> rdataFromBus(31, 16),
"b11".U -> rdataFromBus(31, 24)
))
io.out.bits := LookupTree(func, List(
LsuLb -> Cat(Fill(24, rdata(7)), rdata(7, 0)),
LsuLh -> Cat(Fill(16, rdata(15)), rdata(15, 0)),
LsuLw -> rdata,
LsuLbu -> Cat(0.U(24.W), rdata(7, 0)),
LsuLhu -> Cat(0.U(16.W), rdata(15, 0))
))
}
))
}

View File

@ -32,19 +32,28 @@ object MDUInstr extends HasDecodeConst {
)
}
class MDU extends HasMDUOpType {
def access(src1: UInt, src2: UInt, func: UInt): UInt = {
0.U
/*
val mulRes = (src1.asSInt * src2.asSInt).asUInt
LookupTree(func, 0.U, List(
MduMul -> mulRes(31, 0),
MduMulh -> mulRes(63, 32),
MduDiv -> (src1.asSInt / src2.asSInt).asUInt,
MduDivu -> (src1 / src2),
MduRem -> (src1.asSInt % src2.asSInt).asUInt,
MduRemu -> (src1 % src2)
))
*/
class MDU extends Module with HasMDUOpType {
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 mulRes = (src1.asSInt * src2.asSInt).asUInt
io.out.bits := LookupTree(func, 0.U, List(
MduMul -> mulRes(31, 0),
MduMulh -> mulRes(63, 32),
MduDiv -> (src1.asSInt / src2.asSInt).asUInt,
MduDivu -> (src1 / src2),
MduRem -> (src1.asSInt % src2.asSInt).asUInt,
MduRemu -> (src1 % src2)
))
io.in.ready := true.B
io.out.valid := valid
}