commit
a26cb73dfb
|
|
@ -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)))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
))
|
||||
}
|
||||
))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue