成功生成verilog

This commit is contained in:
Liphen 2023-12-07 16:08:45 +08:00
parent 6f02672358
commit f7ee8c4c87
8 changed files with 243 additions and 115 deletions

View File

@ -44,7 +44,6 @@ class Core(implicit val config: CpuConfig) extends Module {
ctrl.memoryUnit <> memoryUnit.ctrl
ctrl.writeBackUnit <> writeBackUnit.ctrl
ctrl.cacheCtrl.iCache_stall := io.inst.icache_stall
ctrl.cacheCtrl.dCache_stall := io.data.dcache_stall
fetchUnit.memory <> memoryUnit.fetchUnit
fetchUnit.execute <> executeUnit.fetchUnit
@ -120,6 +119,7 @@ class Core(implicit val config: CpuConfig) extends Module {
memoryUnit.dataMemory.in.rdata := io.data.rdata
memoryUnit.dataMemory.in.acc_err := io.data.acc_err
memoryUnit.dataMemory.in.ready := !io.data.dcache_stall
io.data.en := memoryUnit.dataMemory.out.en
io.data.size := memoryUnit.dataMemory.out.rlen
io.data.wen := memoryUnit.dataMemory.out.wen

View File

@ -17,15 +17,16 @@ class Ctrl(implicit val config: CpuConfig) extends Module {
val writeBackUnit = Flipped(new WriteBackCtrl())
})
val inst0_lw_stall = (io.executeUnit.inst(0).mem_wreg) &&
val inst0_lw_stall = (io.executeUnit.inst(0).mem_wreg) && io.executeUnit.inst(0).reg_waddr.orR &&
(io.decoderUnit.inst0.src1.ren && io.decoderUnit.inst0.src1.raddr === io.executeUnit.inst(0).reg_waddr ||
io.decoderUnit.inst0.src2.ren && io.decoderUnit.inst0.src2.raddr === io.executeUnit.inst(0).reg_waddr)
val inst1_lw_stall = (io.executeUnit.inst(1).mem_wreg) &&
val inst1_lw_stall = (io.executeUnit.inst(1).mem_wreg) && io.executeUnit.inst(1).reg_waddr.orR &&
(io.decoderUnit.inst0.src1.ren && io.decoderUnit.inst0.src1.raddr === io.executeUnit.inst(1).reg_waddr ||
io.decoderUnit.inst0.src2.ren && io.decoderUnit.inst0.src2.raddr === io.executeUnit.inst(1).reg_waddr)
val lw_stall = inst0_lw_stall || inst1_lw_stall
// TODO: 这里的stall信号可能不对
val longest_stall = io.executeUnit.fu_stall || io.cacheCtrl.iCache_stall || io.cacheCtrl.dCache_stall
val longest_stall =
io.executeUnit.fu_stall || io.cacheCtrl.iCache_stall || io.memoryUnit.mem_stall
io.fetchUnit.allow_to_go := !io.cacheCtrl.iCache_stall
io.decoderUnit.allow_to_go := !(lw_stall || longest_stall)

View File

@ -55,7 +55,6 @@ class SrcReadSignal extends Bundle {
class CacheCtrl extends Bundle {
val iCache_stall = Output(Bool())
val dCache_stall = Output(Bool())
}
class FetchUnitCtrl extends Bundle {
@ -85,7 +84,7 @@ class ExecuteFuCtrl extends Bundle {
class ExecuteCtrl(implicit val config: CpuConfig) extends Bundle {
val inst = Output(Vec(config.fuNum, new MemRead()))
val fu_stall = Output(Bool())
val flush = Output(Bool())
val flush = Output(Bool())
val allow_to_go = Input(Bool())
val do_flush = Input(Bool())
@ -94,7 +93,8 @@ class ExecuteCtrl(implicit val config: CpuConfig) extends Bundle {
}
class MemoryCtrl extends Bundle {
val flush = Output(Bool())
val flush = Output(Bool())
val mem_stall = Output(Bool())
val allow_to_go = Input(Bool())
val do_flush = Input(Bool())

View File

@ -17,10 +17,16 @@ class CsrMemoryUnit(implicit val config: CpuConfig) extends Bundle {
val info = new InstInfo()
}
)
val set_lr = Bool()
val set_lr_val = Bool()
val set_lr_addr = UInt(DATA_ADDR_WID.W)
})
val out = Output(new Bundle {
val flush = Bool()
val flush_pc = UInt(PC_WID.W)
val lr = Bool()
val lr_addr = UInt(DATA_ADDR_WID.W)
})
}
@ -104,20 +110,20 @@ class Csr(implicit val config: CpuConfig) extends Module with HasCSRConst {
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")
val set_lr = WireInit(Bool(), false.B)
val set_lr_val = WireInit(Bool(), false.B)
val set_lr_addr = WireInit(UInt(DATA_ADDR_WID.W), 0.U)
val lr = RegInit(Bool(), false.B)
val lr_addr = RegInit(UInt(DATA_ADDR_WID.W), 0.U)
set_lr := io.memoryUnit.in.set_lr
set_lr_val := io.memoryUnit.in.set_lr_val
set_lr_addr := io.memoryUnit.in.set_lr_addr
io.memoryUnit.out.lr := lr
io.memoryUnit.out.lr_addr := lr_addr
when(setLr) {
lr := setLrVal
lrAddr := setLrAddr
when(set_lr) {
lr := set_lr_val
lr_addr := set_lr_addr
}
// Side Effect

View File

@ -113,6 +113,7 @@ class ExecuteUnit(implicit val config: CpuConfig) extends Module {
io.memoryStage.inst0.pc := io.executeStage.inst0.pc
io.memoryStage.inst0.info := io.executeStage.inst0.info
io.memoryStage.inst0.src_info := io.executeStage.inst0.src_info
io.memoryStage.inst0.rd_info.wdata(FuType.alu) := fu.inst(0).result.alu
io.memoryStage.inst0.rd_info.wdata(FuType.mdu) := fu.inst(0).result.mdu
io.memoryStage.inst0.rd_info.wdata(FuType.csr) := io.csr.out.rdata
@ -137,6 +138,7 @@ class ExecuteUnit(implicit val config: CpuConfig) extends Module {
io.memoryStage.inst1.pc := io.executeStage.inst1.pc
io.memoryStage.inst1.info := io.executeStage.inst1.info
io.memoryStage.inst1.src_info := io.executeStage.inst1.src_info
io.memoryStage.inst1.rd_info.wdata(FuType.alu) := fu.inst(1).result.alu
io.memoryStage.inst1.rd_info.wdata(FuType.mdu) := fu.inst(1).result.mdu
io.memoryStage.inst1.rd_info.wdata(FuType.csr) := io.csr.out.rdata

View File

@ -5,10 +5,12 @@ import chisel3.util._
import cpu.defines._
import cpu.defines.Const._
import cpu.CpuConfig
import chisel3.util.experimental.BoringUtils
class DataMemoryAccess_DataMemory extends Bundle {
val in = Input(new Bundle {
val acc_err = Bool()
val ready = Bool()
val rdata = UInt(DATA_WID.W)
})
val out = Output(new Bundle {
@ -21,85 +23,170 @@ class DataMemoryAccess_DataMemory extends Bundle {
})
}
class DataMemoryAccess_MemoryUnit extends Bundle {
val in = Input(new Bundle {
val mem_en = Bool()
val info = new InstInfo()
val src_info = new SrcInfo()
val ex = new ExceptionInfo()
val lr = Bool()
val lr_addr = UInt(DATA_ADDR_WID.W)
})
val out = Output(new Bundle {
val ready = Bool()
val rdata = UInt(DATA_WID.W)
val ex = new ExceptionInfo()
val set_lr = Bool()
val set_lr_val = Bool()
val set_lr_addr = UInt(DATA_ADDR_WID.W)
})
}
class DataMemoryAccess(implicit val config: CpuConfig) extends Module {
val io = IO(new Bundle {
val memoryUnit = new Bundle {
val in = Input(new Bundle {
val mem_en = Bool()
val info = new InstInfo()
val mem_wdata = UInt(DATA_WID.W)
val mem_addr = UInt(DATA_ADDR_WID.W)
val mem_sel = Vec(config.fuNum, Bool())
val ex = Vec(config.fuNum, new ExceptionInfo())
})
val out = Output(new Bundle {
val acc_err = Bool()
val rdata = Output(UInt(DATA_WID.W))
})
}
val memoryUnit = new DataMemoryAccess_MemoryUnit()
val dataMemory = new DataMemoryAccess_DataMemory()
})
val mem_addr = io.memoryUnit.in.mem_addr
val mem_addr2 = mem_addr(1, 0)
val mem_rdata = io.dataMemory.in.rdata
val mem_wdata = io.memoryUnit.in.mem_wdata
val op = io.memoryUnit.in.info.op
io.dataMemory.out.en := io.memoryUnit.in.mem_en &&
(io.memoryUnit.in.mem_sel(0) &&
!(HasExcInt(io.memoryUnit.in.ex(0))) ||
io.memoryUnit.in.mem_sel(1) &&
!(HasExcInt(io.memoryUnit.in.ex(0))) && !(HasExcInt(io.memoryUnit.in.ex(1))))
io.dataMemory.out.addr := mem_addr
val rdata = LookupTree(
mem_addr(2, 0),
List(
"b000".U -> mem_rdata(63, 0),
"b001".U -> mem_rdata(63, 8),
"b010".U -> mem_rdata(63, 16),
"b011".U -> mem_rdata(63, 24),
"b100".U -> mem_rdata(63, 32),
"b101".U -> mem_rdata(63, 40),
"b110".U -> mem_rdata(63, 48),
"b111".U -> mem_rdata(63, 56)
)
)
io.memoryUnit.out.acc_err := io.dataMemory.in.acc_err
io.memoryUnit.out.rdata := MuxLookup(op, rdata(XLEN - 1, 0))(
List(
LSUOpType.lb -> SignedExtend(rdata(7, 0), XLEN),
LSUOpType.lh -> SignedExtend(rdata(15, 0), XLEN),
LSUOpType.lw -> SignedExtend(rdata(31, 0), XLEN),
LSUOpType.lbu -> ZeroExtend(rdata(7, 0), XLEN),
LSUOpType.lhu -> ZeroExtend(rdata(15, 0), XLEN),
LSUOpType.lwu -> ZeroExtend(rdata(31, 0), XLEN)
)
)
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
)
)
val atomAlu = Module(new AtomAlu()).io
val lsExe = Module(new LSExe()).io
val valid = io.memoryUnit.in.mem_en
val src1 = io.memoryUnit.in.src_info.src1_data
val src2 = io.memoryUnit.in.src_info.src2_data
val func = io.memoryUnit.in.info.op
val inst = io.memoryUnit.in.info.inst
val storeReq = valid & LSUOpType.isStore(func)
val loadReq = valid & LSUOpType.isLoad(func)
val atomReq = valid & LSUOpType.isAtom(func)
val amoReq = valid & LSUOpType.isAMO(func)
val lrReq = valid & LSUOpType.isLR(func)
val scReq = valid & LSUOpType.isSC(func)
val aq = inst(26)
val rl = inst(25)
val funct3 = inst(14, 12)
val atomWidthW = !funct3(0)
val atomWidthD = funct3(0)
// Atom LR/SC Control Bits
val setLr = Wire(Bool())
val setLrVal = Wire(Bool())
val setLrAddr = Wire(UInt(DATA_ADDR_WID.W))
val lr = WireInit(Bool(), false.B)
val lrAddr = WireInit(UInt(DATA_ADDR_WID.W), DontCare)
io.memoryUnit.out.set_lr := setLr
io.memoryUnit.out.set_lr_val := setLrVal
io.memoryUnit.out.set_lr_addr := setLrAddr
lr := io.memoryUnit.in.lr
lrAddr := io.memoryUnit.in.lr_addr
val s_idle :: s_lr :: s_sc :: s_amo_l :: s_amo_a :: s_amo_s :: Nil = Enum(6)
val state = RegInit(s_idle)
val atomMemReg = Reg(UInt(XLEN.W))
val atomRegReg = Reg(UInt(XLEN.W))
atomAlu.in.rdata := atomMemReg
atomAlu.in.wdata := io.dataMemory.out.wdata
atomAlu.in.info := io.memoryUnit.in.info
val scInvalid = (src1 =/= lrAddr || !lr) && scReq
lsExe.in.info := io.memoryUnit.in.info
lsExe.in.mem_addr := 0.U
lsExe.in.mem_en := false.B
lsExe.in.wdata := 0.U
io.memoryUnit.out.ready := false.B
switch(state) {
is(s_idle) { // calculate address
lsExe.in.mem_en := io.memoryUnit.in.mem_en && !atomReq
lsExe.in.mem_addr := src1 + src2
lsExe.in.info.op := func
lsExe.in.wdata := io.memoryUnit.in.src_info.src2_data
io.memoryUnit.out.ready := lsExe.dataMemory.in.ready || scInvalid
state := s_idle
when(amoReq) { state := s_amo_l }
when(lrReq) { state := s_lr }
when(scReq) { state := Mux(scInvalid, s_idle, s_sc) }
}
is(s_amo_l) {
lsExe.in.mem_en := true.B
lsExe.in.mem_addr := src1
lsExe.in.info.op := Mux(atomWidthD, LSUOpType.ld, LSUOpType.lw)
lsExe.in.wdata := DontCare
io.memoryUnit.out.ready := false.B
when(lsExe.dataMemory.in.ready) {
state := s_amo_a;
}
atomMemReg := lsExe.out.rdata
atomRegReg := lsExe.out.rdata
}
is(s_amo_a) {
lsExe.in.mem_en := false.B
lsExe.in.mem_addr := DontCare
lsExe.in.info.op := DontCare
lsExe.in.wdata := DontCare
io.memoryUnit.out.ready := false.B
state := s_amo_s
atomMemReg := atomAlu.out.result
}
is(s_amo_s) {
lsExe.in.mem_en := true.B
lsExe.in.mem_addr := src1
lsExe.in.info.op := Mux(atomWidthD, LSUOpType.sd, LSUOpType.sw)
lsExe.in.wdata := atomMemReg
io.memoryUnit.out.ready := lsExe.dataMemory.in.ready
when(lsExe.dataMemory.in.ready) {
state := s_idle;
}
}
is(s_lr) {
lsExe.in.mem_en := true.B
lsExe.in.mem_addr := src1
lsExe.in.info.op := Mux(atomWidthD, LSUOpType.ld, LSUOpType.lw)
lsExe.in.wdata := DontCare
io.memoryUnit.out.ready := lsExe.dataMemory.in.ready
when(lsExe.dataMemory.in.ready) {
state := s_idle;
}
}
is(s_sc) {
lsExe.in.mem_en := true.B
lsExe.in.mem_addr := src1
lsExe.in.info.op := Mux(atomWidthD, LSUOpType.sd, LSUOpType.sw)
lsExe.in.wdata := io.memoryUnit.in.src_info.src2_data
io.memoryUnit.out.ready := lsExe.dataMemory.in.ready
when(lsExe.dataMemory.in.ready) {
state := s_idle;
}
}
}
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)
when(lsExe.out.loadAddrMisaligned || lsExe.out.storeAddrMisaligned) {
state := s_idle
io.memoryUnit.out.ready := true.B
io.memoryUnit.out.ready := true.B
}
io.dataMemory.out.wdata := genWdata(mem_wdata, op(1, 0))
io.dataMemory.out.wen := LSUOpType.isStore(op) && io.memoryUnit.in.mem_en
io.dataMemory.out.wstrb := genWmask(mem_addr, op(1, 0))
io.dataMemory.out.rlen := op(1, 0)
setLr := io.memoryUnit.out.ready && (lrReq || scReq)
setLrVal := lrReq
setLrAddr := src1
io.dataMemory <> lsExe.dataMemory
io.memoryUnit.out.ex := io.memoryUnit.in.ex
io.memoryUnit.out.ex.exception(loadAddrMisaligned) := lsExe.out.loadAddrMisaligned
io.memoryUnit.out.ex.exception(storeAddrMisaligned) := lsExe.out.storeAddrMisaligned
io.memoryUnit.out.ex.exception(loadAccessFault) := lsExe.out.loadAccessFault
io.memoryUnit.out.ex.exception(storeAccessFault) := lsExe.out.storeAccessFault
io.memoryUnit.out.rdata := lsExe.out.rdata
}

View File

@ -18,6 +18,8 @@ class LSExe extends Module {
val out = Output(new Bundle {
val loadAddrMisaligned = Bool()
val storeAddrMisaligned = Bool()
val loadAccessFault = Bool()
val storeAccessFault = Bool()
val rdata = UInt(DATA_WID.W)
})
})
@ -136,5 +138,7 @@ class LSExe extends Module {
val is_amo = valid && LSUOpType.isAMO(op)
io.out.rdata := Mux(partialLoad, rdataPartialLoad, rdataSel)
io.out.loadAddrMisaligned := valid && !isStore && !is_amo && !addrAligned
io.out.loadAccessFault := valid && !isStore && !is_amo && acc_err
io.out.storeAddrMisaligned := valid && (isStore || is_amo) && !addrAligned
io.out.storeAccessFault := valid && (isStore || is_amo) && acc_err
}

View File

@ -24,16 +24,37 @@ class MemoryUnit(implicit val config: CpuConfig) extends Module {
})
val dataMemoryAccess = Module(new DataMemoryAccess()).io
dataMemoryAccess.memoryUnit.in.mem_en := io.memoryStage.inst0.mem.en
dataMemoryAccess.memoryUnit.in.info := io.memoryStage.inst0.mem.info
dataMemoryAccess.memoryUnit.in.mem_wdata := io.memoryStage.inst0.mem.wdata
dataMemoryAccess.memoryUnit.in.mem_addr := io.memoryStage.inst0.mem.addr
dataMemoryAccess.memoryUnit.in.mem_sel := io.memoryStage.inst0.mem.sel
dataMemoryAccess.memoryUnit.in.ex(0) := io.memoryStage.inst0.ex
dataMemoryAccess.memoryUnit.in.ex(1) := io.memoryStage.inst1.ex
dataMemoryAccess.dataMemory.in.acc_err := io.dataMemory.in.acc_err
dataMemoryAccess.dataMemory.in.rdata := io.dataMemory.in.rdata
io.dataMemory.out := dataMemoryAccess.dataMemory.out
val mem_sel = VecInit(
io.memoryStage.inst0.info.valid &&
io.memoryStage.inst0.info.fusel === FuType.lsu &&
!HasExcInt(io.memoryStage.inst0.ex),
io.memoryStage.inst1.info.valid &&
io.memoryStage.inst1.info.fusel === FuType.lsu &&
!HasExcInt(io.memoryStage.inst1.ex) && !HasExcInt(io.memoryStage.inst0.ex)
)
dataMemoryAccess.memoryUnit.in.mem_en := mem_sel.reduce(_ || _)
dataMemoryAccess.memoryUnit.in.info := MuxCase(
0.U.asTypeOf(new InstInfo()),
Seq(
mem_sel(0) -> io.memoryStage.inst0.info,
mem_sel(1) -> io.memoryStage.inst1.info
)
)
dataMemoryAccess.memoryUnit.in.src_info := MuxCase(
0.U.asTypeOf(new SrcInfo()),
Seq(
mem_sel(0) -> io.memoryStage.inst0.src_info,
mem_sel(1) -> io.memoryStage.inst1.src_info
)
)
dataMemoryAccess.memoryUnit.in.ex := MuxCase(
0.U.asTypeOf(new ExceptionInfo()),
Seq(
mem_sel(0) -> io.memoryStage.inst0.ex,
mem_sel(1) -> io.memoryStage.inst1.ex
)
)
dataMemoryAccess.dataMemory <> io.dataMemory
io.decoderUnit(0).wen := io.writeBackStage.inst0.info.reg_wen
io.decoderUnit(0).waddr := io.writeBackStage.inst0.info.reg_waddr
@ -46,22 +67,22 @@ class MemoryUnit(implicit val config: CpuConfig) extends Module {
io.writeBackStage.inst0.info := io.memoryStage.inst0.info
io.writeBackStage.inst0.rd_info.wdata := io.memoryStage.inst0.rd_info.wdata
io.writeBackStage.inst0.rd_info.wdata(FuType.lsu) := dataMemoryAccess.memoryUnit.out.rdata
io.writeBackStage.inst0.ex := io.memoryStage.inst0.ex
io.writeBackStage.inst0.ex.exception(loadAccessFault) := io.memoryStage.inst0.mem.sel(0) &&
LSUOpType.isLoad(io.memoryStage.inst0.info.op) && dataMemoryAccess.memoryUnit.out.acc_err
io.writeBackStage.inst0.ex.exception(storeAccessFault) := io.memoryStage.inst0.mem.sel(0) &&
LSUOpType.isStore(io.memoryStage.inst0.info.op) && dataMemoryAccess.memoryUnit.out.acc_err
io.writeBackStage.inst0.ex := Mux(
mem_sel(0),
dataMemoryAccess.memoryUnit.out.ex,
io.memoryStage.inst0.ex
)
io.writeBackStage.inst0.commit := io.memoryStage.inst0.info.valid
io.writeBackStage.inst1.pc := io.memoryStage.inst1.pc
io.writeBackStage.inst1.info := io.memoryStage.inst1.info
io.writeBackStage.inst1.rd_info.wdata := io.memoryStage.inst1.rd_info.wdata
io.writeBackStage.inst1.rd_info.wdata(FuType.lsu) := dataMemoryAccess.memoryUnit.out.rdata
io.writeBackStage.inst1.ex := io.memoryStage.inst1.ex
io.writeBackStage.inst1.ex.exception(loadAccessFault) := io.memoryStage.inst0.mem.sel(1) &&
LSUOpType.isLoad(io.memoryStage.inst1.info.op) && dataMemoryAccess.memoryUnit.out.acc_err
io.writeBackStage.inst1.ex.exception(storeAccessFault) := io.memoryStage.inst0.mem.sel(1) &&
LSUOpType.isStore(io.memoryStage.inst1.info.op) && dataMemoryAccess.memoryUnit.out.acc_err
io.writeBackStage.inst1.ex := Mux(
mem_sel(1),
dataMemoryAccess.memoryUnit.out.ex,
io.memoryStage.inst1.ex
)
io.writeBackStage.inst1.commit := io.memoryStage.inst1.info.valid &&
!(HasExcInt(io.writeBackStage.inst0.ex))
@ -80,8 +101,15 @@ class MemoryUnit(implicit val config: CpuConfig) extends Module {
0.U.asTypeOf(new InstInfo())
)
io.csr.in.set_lr := dataMemoryAccess.memoryUnit.out.set_lr && io.ctrl.allow_to_go
io.csr.in.set_lr_val := dataMemoryAccess.memoryUnit.out.set_lr_val
io.csr.in.set_lr_addr := dataMemoryAccess.memoryUnit.out.set_lr_addr
dataMemoryAccess.memoryUnit.in.lr := io.csr.out.lr
dataMemoryAccess.memoryUnit.in.lr_addr := io.csr.out.lr_addr
io.fetchUnit.flush := io.csr.out.flush && io.ctrl.allow_to_go
io.fetchUnit.target := Mux(io.csr.out.flush, io.csr.out.flush_pc, io.writeBackStage.inst0.pc + 4.U)
io.ctrl.flush := io.fetchUnit.flush
io.ctrl.flush := io.fetchUnit.flush
io.ctrl.mem_stall := !dataMemoryAccess.memoryUnit.out.ready && dataMemoryAccess.memoryUnit.in.mem_en
}