refactor: 将访存全部重构一下

This commit is contained in:
Liphen 2023-12-07 15:02:22 +08:00
parent 681162954f
commit 6f02672358
7 changed files with 223 additions and 138 deletions

View File

@ -103,6 +103,23 @@ class Csr(implicit val config: CpuConfig) extends Module with HasCSRConst {
val rdata = Wire(UInt(XLEN.W))
val wdata = Wire(UInt(XLEN.W))
// Atom LR/SC Control Bits
val setLr = WireInit(Bool(), false.B)
val setLrVal = WireInit(Bool(), false.B)
val setLrAddr = WireInit(UInt(XLEN.W), DontCare) //TODO : need check
val lr = RegInit(Bool(), false.B)
val lrAddr = RegInit(UInt(XLEN.W), 0.U)
BoringUtils.addSink(setLr, "set_lr")
BoringUtils.addSink(setLrVal, "set_lr_val")
BoringUtils.addSink(setLrAddr, "set_lr_addr")
BoringUtils.addSource(lr, "lr")
BoringUtils.addSource(lrAddr, "lr_addr")
when(setLr) {
lr := setLrVal
lrAddr := setLrAddr
}
// Side Effect
def mstatusUpdateSideEffect(mstatus: UInt): UInt = {
val mstatusOld = WireInit(mstatus.asTypeOf(new Mstatus))
@ -325,8 +342,8 @@ class Csr(implicit val config: CpuConfig) extends Module with HasCSRConst {
mstatusNew.pie.m := true.B
mstatusNew.mpp := ModeU
mstatus := mstatusNew.asUInt
// lr := false.B //TODO: add原子操作
ret_target := mepc(VADDR_WID - 1, 0)
lr := false.B
ret_target := mepc(VADDR_WID - 1, 0)
}
io.decoderUnit.priv_mode := priv_mode

View File

@ -1,92 +0,0 @@
package cpu.pipeline.execute
import chisel3._
import chisel3.util._
import cpu.CpuConfig
import cpu.defines._
import cpu.defines.Const._
class ExeAccessMemCtrl(implicit val config: CpuConfig) extends Module {
val io = IO(new Bundle {
val mem = new Bundle {
val out = Output(new Bundle {
val en = Bool()
val ren = Bool()
val wen = Bool()
val info = new InstInfo()
val addr = UInt(DATA_ADDR_WID.W)
val wdata = UInt(DATA_WID.W)
})
}
val inst = Vec(
config.fuNum,
new Bundle {
val info = Input(new InstInfo())
val src_info = Input(new SrcInfo())
val ex = new Bundle {
val in = Input(new ExceptionInfo())
val out = Output(new ExceptionInfo())
}
val mem_sel = Output(Bool())
}
)
})
io.mem.out.en := io.inst.map(_.mem_sel).reduce(_ || _)
io.mem.out.ren := io.inst(0).mem_sel && LSUOpType.isLoad(io.inst(0).info.op) ||
io.inst(1).mem_sel && LSUOpType.isLoad(io.inst(1).info.op)
io.mem.out.wen := io.inst(0).mem_sel && LSUOpType.isStore(io.inst(0).info.op) ||
io.inst(1).mem_sel && LSUOpType.isStore(io.inst(1).info.op)
io.mem.out.info := Mux1H(
Seq(
(io.inst(0).info.fusel === FuType.lsu) -> io.inst(0).info,
(io.inst(1).info.fusel === FuType.lsu) -> io.inst(1).info
)
)
val mem_addr = Wire(Vec(config.fuNum, UInt(DATA_ADDR_WID.W)))
mem_addr(0) := io.inst(0).src_info.src1_data + io.inst(0).info.imm
mem_addr(1) := io.inst(1).src_info.src1_data + io.inst(1).info.imm
io.mem.out.addr := Mux1H(
Seq(
(io.inst(0).info.fusel === FuType.lsu) -> mem_addr(0),
(io.inst(1).info.fusel === FuType.lsu) -> mem_addr(1)
)
)
io.mem.out.wdata := Mux1H(
Seq(
(io.inst(0).info.fusel === FuType.lsu) ->
io.inst(0).src_info.src2_data,
(io.inst(1).info.fusel === FuType.lsu) ->
io.inst(1).src_info.src2_data
)
)
val addr_aligned = Wire(Vec(config.fuNum, Bool()))
for (i <- 0 until config.fuNum) {
addr_aligned(i) := LookupTree(
io.inst(i).info.op(1, 0),
List(
"b00".U -> true.B, //b
"b01".U -> (mem_addr(i)(0) === 0.U), //h
"b10".U -> (mem_addr(i)(1, 0) === 0.U), //w
"b11".U -> (mem_addr(i)(2, 0) === 0.U) //d
)
)
}
for (i <- 0 until config.fuNum) {
val store_inst = LSUOpType.isStore(io.inst(i).info.op)
io.inst(i).ex.out := io.inst(i).ex.in
io.inst(i).ex.out.exception(loadAddrMisaligned) := !store_inst && !addr_aligned(i)
io.inst(i).ex.out.exception(storeAddrMisaligned) := store_inst && !addr_aligned(i)
io.inst(i).ex.out.tval := Mux(
io.inst(i).ex.in.exception.asUInt.orR,
io.inst(i).ex.in.tval,
mem_addr(i)
)
}
io.inst(0).mem_sel := (io.inst(0).info.fusel === FuType.lsu) &&
!(HasExcInt(io.inst(0).ex.out)) && io.inst(0).info.valid
io.inst(1).mem_sel := (io.inst(1).info.fusel === FuType.lsu) &&
!(HasExcInt(io.inst(0).ex.out)) && !(HasExcInt(io.inst(1).ex.out)) && io.inst(1).info.valid
}

View File

@ -33,8 +33,7 @@ class ExecuteUnit(implicit val config: CpuConfig) extends Module {
val memoryStage = Output(new ExecuteUnitMemoryUnit())
})
val fu = Module(new Fu()).io
val accessMemCtrl = Module(new ExeAccessMemCtrl()).io
val fu = Module(new Fu()).io
val valid = VecInit(
io.executeStage.inst0.info.valid && io.ctrl.allow_to_go,
@ -88,13 +87,6 @@ class ExecuteUnit(implicit val config: CpuConfig) extends Module {
fusel(1) === FuType.lsu && valid(1) &&
!(HasExcInt(io.executeStage.inst1.ex))
)
// input accessMemCtrl
accessMemCtrl.inst(0).info := Mux(is_lsu(0), io.executeStage.inst0.info, 0.U.asTypeOf(new InstInfo()))
accessMemCtrl.inst(0).src_info := Mux(is_lsu(0), io.executeStage.inst0.src_info, 0.U.asTypeOf(new SrcInfo()))
accessMemCtrl.inst(0).ex.in := Mux(is_lsu(0), io.executeStage.inst0.ex, 0.U.asTypeOf(new ExceptionInfo()))
accessMemCtrl.inst(1).info := Mux(is_lsu(1), io.executeStage.inst1.info, 0.U.asTypeOf(new InstInfo()))
accessMemCtrl.inst(1).src_info := Mux(is_lsu(1), io.executeStage.inst1.src_info, 0.U.asTypeOf(new SrcInfo()))
accessMemCtrl.inst(1).ex.in := Mux(is_lsu(1), io.executeStage.inst1.ex, 0.U.asTypeOf(new ExceptionInfo()))
// input fu
fu.ctrl <> io.ctrl.fu
@ -119,14 +111,6 @@ class ExecuteUnit(implicit val config: CpuConfig) extends Module {
io.ctrl.fu_stall := fu.stall_req
io.memoryStage.inst0.mem.en := accessMemCtrl.mem.out.en
io.memoryStage.inst0.mem.ren := accessMemCtrl.mem.out.ren
io.memoryStage.inst0.mem.wen := accessMemCtrl.mem.out.wen
io.memoryStage.inst0.mem.addr := accessMemCtrl.mem.out.addr
io.memoryStage.inst0.mem.wdata := accessMemCtrl.mem.out.wdata
io.memoryStage.inst0.mem.sel := accessMemCtrl.inst.map(_.mem_sel)
io.memoryStage.inst0.mem.info := accessMemCtrl.mem.out.info
io.memoryStage.inst0.pc := io.executeStage.inst0.pc
io.memoryStage.inst0.info := io.executeStage.inst0.info
io.memoryStage.inst0.rd_info.wdata(FuType.alu) := fu.inst(0).result.alu
@ -141,7 +125,6 @@ class ExecuteUnit(implicit val config: CpuConfig) extends Module {
io.executeStage.inst0.ex,
MuxLookup(io.executeStage.inst0.info.fusel, io.executeStage.inst0.ex)(
Seq(
FuType.lsu -> accessMemCtrl.inst(0).ex.out,
FuType.csr -> io.csr.out.ex
)
)
@ -166,7 +149,6 @@ class ExecuteUnit(implicit val config: CpuConfig) extends Module {
io.executeStage.inst1.ex,
MuxLookup(io.executeStage.inst1.info.fusel, io.executeStage.inst1.ex)(
Seq(
FuType.lsu -> accessMemCtrl.inst(1).ex.out,
FuType.csr -> io.csr.out.ex
)
)

View File

@ -0,0 +1,48 @@
package cpu.pipeline.memory
import chisel3._
import chisel3.util._
import cpu.defines._
import cpu.defines.Const._
import cpu.CpuConfig
class AtomAlu extends Module {
val io = IO(new Bundle {
val in = Input(new Bundle {
val rdata = Input(UInt(XLEN.W)) // load data
val wdata = Input(UInt(XLEN.W)) // reg data
val info = new InstInfo()
})
val out = Output(new Bundle {
val result = Output(UInt(XLEN.W))
})
})
val src1 = io.in.rdata
val src2 = io.in.wdata
val op = io.in.info.op
val is_sub = !LSUOpType.isAdd(op)
val sum = (src1 +& (src2 ^ Fill(XLEN, is_sub))) + is_sub
val oxr = src1 ^ src2
val sltu = !sum(XLEN)
val slt = oxr(XLEN - 1) ^ sltu
val is_word = !io.in.info.inst(12)
val res = LookupTreeDefault(
op(5, 0),
sum,
List(
LSUOpType.amoswap -> src2,
LSUOpType.amoadd -> sum,
LSUOpType.amoxor -> oxr,
LSUOpType.amoand -> (src1 & src2),
LSUOpType.amoor -> (src1 | src2),
LSUOpType.amomin -> Mux(slt(0), src1, src2),
LSUOpType.amomax -> Mux(slt(0), src2, src1),
LSUOpType.amominu -> Mux(sltu(0), src1, src2),
LSUOpType.amomaxu -> Mux(sltu(0), src2, src1)
)
)
io.out.result := Mux(is_word, SignedExtend(res(31, 0), 64), res(XLEN - 1, 0))
}

View File

@ -0,0 +1,140 @@
package cpu.pipeline.memory
import chisel3._
import chisel3.util._
import cpu.defines._
import cpu.defines.Const._
import cpu.CpuConfig
class LSExe extends Module {
val io = IO(new Bundle {
val dataMemory = new DataMemoryAccess_DataMemory()
val in = Input(new Bundle {
val mem_en = Bool()
val mem_addr = UInt(DATA_ADDR_WID.W)
val wdata = UInt(DATA_WID.W)
val info = new InstInfo()
})
val out = Output(new Bundle {
val loadAddrMisaligned = Bool()
val storeAddrMisaligned = Bool()
val rdata = UInt(DATA_WID.W)
})
})
def genWmask(addr: UInt, sizeEncode: UInt): UInt = {
LookupTree(
sizeEncode,
List(
"b00".U -> 0x1.U, //0001 << addr(2:0)
"b01".U -> 0x3.U, //0011
"b10".U -> 0xf.U, //1111
"b11".U -> 0xff.U //11111111
)
) << addr(2, 0)
}
def genWdata(data: UInt, sizeEncode: UInt): UInt = {
LookupTree(
sizeEncode,
List(
"b00".U -> Fill(8, data(7, 0)),
"b01".U -> Fill(4, data(15, 0)),
"b10".U -> Fill(2, data(31, 0)),
"b11".U -> data
)
)
}
def genWmask32(addr: UInt, sizeEncode: UInt): UInt = {
LookupTree(
sizeEncode,
List(
"b00".U -> 0x1.U, //0001 << addr(1:0)
"b01".U -> 0x3.U, //0011
"b10".U -> 0xf.U //1111
)
) << addr(1, 0)
}
def genWdata32(data: UInt, sizeEncode: UInt): UInt = {
LookupTree(
sizeEncode,
List(
"b00".U -> Fill(4, data(7, 0)),
"b01".U -> Fill(2, data(15, 0)),
"b10".U -> data
)
)
}
val valid = io.in.mem_en
val addr = io.in.mem_addr
val addrLatch = RegNext(addr)
val op = io.in.info.op
val isStore = valid && LSUOpType.isStore(op)
val partialLoad = !isStore && (op =/= LSUOpType.ld)
val size = op(1, 0)
val reqAddr = if (XLEN == 32) SignedExtend(addr, VADDR_WID) else addr(VADDR_WID - 1, 0)
val reqWdata = if (XLEN == 32) genWdata32(io.in.wdata, size) else genWdata(io.in.wdata, size)
val reqWmask = if (XLEN == 32) genWmask32(addr, size) else genWmask(addr, size)
io.dataMemory.out.en := valid && !io.out.storeAddrMisaligned && !io.out.loadAddrMisaligned
io.dataMemory.out.rlen := size
io.dataMemory.out.wen := isStore
io.dataMemory.out.wstrb := reqWmask
io.dataMemory.out.addr := reqAddr
io.dataMemory.out.wdata := reqWdata
val rdata = io.dataMemory.in.rdata
val acc_err = io.dataMemory.in.acc_err
val rdataSel64 = LookupTree(
addrLatch(2, 0),
List(
"b000".U -> rdata(63, 0),
"b001".U -> rdata(63, 8),
"b010".U -> rdata(63, 16),
"b011".U -> rdata(63, 24),
"b100".U -> rdata(63, 32),
"b101".U -> rdata(63, 40),
"b110".U -> rdata(63, 48),
"b111".U -> rdata(63, 56)
)
)
val rdataSel32 = LookupTree(
addrLatch(1, 0),
List(
"b00".U -> rdata(31, 0),
"b01".U -> rdata(31, 8),
"b10".U -> rdata(31, 16),
"b11".U -> rdata(31, 24)
)
)
val rdataSel = if (XLEN == 32) rdataSel32 else rdataSel64
val rdataPartialLoad = LookupTree(
op,
List(
LSUOpType.lb -> SignedExtend(rdataSel(7, 0), XLEN),
LSUOpType.lh -> SignedExtend(rdataSel(15, 0), XLEN),
LSUOpType.lw -> SignedExtend(rdataSel(31, 0), XLEN),
LSUOpType.lbu -> ZeroExtend(rdataSel(7, 0), XLEN),
LSUOpType.lhu -> ZeroExtend(rdataSel(15, 0), XLEN),
LSUOpType.lwu -> ZeroExtend(rdataSel(31, 0), XLEN)
)
)
val addrAligned = LookupTree(
op(1, 0),
List(
"b00".U -> true.B, //b
"b01".U -> (addr(0) === 0.U), //h
"b10".U -> (addr(1, 0) === 0.U), //w
"b11".U -> (addr(2, 0) === 0.U) //d
)
)
val is_amo = valid && LSUOpType.isAMO(op)
io.out.rdata := Mux(partialLoad, rdataPartialLoad, rdataSel)
io.out.loadAddrMisaligned := valid && !isStore && !is_amo && !addrAligned
io.out.storeAddrMisaligned := valid && (isStore || is_amo) && !addrAligned
}

View File

@ -6,29 +6,17 @@ import cpu.defines._
import cpu.defines.Const._
import cpu.CpuConfig
class ExeMemInst1 extends Bundle {
val pc = UInt(PC_WID.W)
val info = new InstInfo()
val rd_info = new RdInfo()
val ex = new ExceptionInfo()
}
class ExeMemInst0(implicit val config: CpuConfig) extends ExeMemInst1 {
val mem = new Bundle {
val en = Bool()
val ren = Bool()
val wen = Bool()
val info = new InstInfo()
val addr = UInt(DATA_ADDR_WID.W)
val wdata = UInt(DATA_WID.W)
val sel = Vec(config.fuNum, Bool())
}
class ExeMemInst extends Bundle {
val pc = UInt(PC_WID.W)
val info = new InstInfo()
val rd_info = new RdInfo()
val src_info = new SrcInfo()
val ex = new ExceptionInfo()
}
class ExecuteUnitMemoryUnit(implicit val config: CpuConfig) extends Bundle {
val inst0 = new ExeMemInst0()
val inst1 = new ExeMemInst1()
val inst0 = new ExeMemInst()
val inst1 = new ExeMemInst()
}
class MemoryStage(implicit val config: CpuConfig) extends Module {
@ -40,12 +28,12 @@ class MemoryStage(implicit val config: CpuConfig) extends Module {
val executeUnit = Input(new ExecuteUnitMemoryUnit())
val memoryUnit = Output(new ExecuteUnitMemoryUnit())
})
val inst0 = RegInit(0.U.asTypeOf(new ExeMemInst0()))
val inst1 = RegInit(0.U.asTypeOf(new ExeMemInst1()))
val inst0 = RegInit(0.U.asTypeOf(new ExeMemInst()))
val inst1 = RegInit(0.U.asTypeOf(new ExeMemInst()))
when(io.ctrl.clear) {
inst0 := 0.U.asTypeOf(new ExeMemInst0())
inst1 := 0.U.asTypeOf(new ExeMemInst1())
inst0 := 0.U.asTypeOf(new ExeMemInst())
inst1 := 0.U.asTypeOf(new ExeMemInst())
}.elsewhen(io.ctrl.allow_to_go) {
inst0 := io.executeUnit.inst0
inst1 := io.executeUnit.inst1

View File

@ -2,10 +2,12 @@ import cpu._
import circt.stage._
import cpu.pipeline.execute.Csr
import cpu.pipeline.memory.LSExe
import cpu.pipeline.memory.AtomAlu
object TestMain extends App {
implicit val config = new CpuConfig()
def top = new Csr()
def top = new AtomAlu()
val useMFC = false // use MLIR-based firrtl compiler
val generator = Seq(chisel3.stage.ChiselGeneratorAnnotation(() => top))
if (useMFC) {