refactor: 将访存全部重构一下
This commit is contained in:
parent
681162954f
commit
6f02672358
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
}
|
|
@ -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
|
||||
)
|
||||
)
|
||||
|
|
|
@ -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))
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue