重构了下core
This commit is contained in:
parent
61930afee6
commit
ebbdd5b3b7
|
@ -1,161 +1,147 @@
|
|||
// package cpu
|
||||
package cpu
|
||||
|
||||
// import chisel3._
|
||||
// import chisel3.util._
|
||||
// import chisel3.internal.DontCareBinding
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import chisel3.internal.DontCareBinding
|
||||
|
||||
// import defines._
|
||||
// import defines.Const._
|
||||
// import pipeline.fetch._
|
||||
// import pipeline.decoder._
|
||||
// import pipeline.execute._
|
||||
// import pipeline.memory._
|
||||
// import pipeline.writeback._
|
||||
// import ctrl._
|
||||
// import mmu._
|
||||
// import chisel3.util.experimental.decode.decoder
|
||||
// import cpu.pipeline.fetch.InstFifo
|
||||
import defines._
|
||||
import defines.Const._
|
||||
import pipeline.fetch._
|
||||
import pipeline.decoder._
|
||||
import pipeline.execute._
|
||||
import pipeline.memory._
|
||||
import pipeline.writeback._
|
||||
import ctrl._
|
||||
import mmu._
|
||||
import chisel3.util.experimental.decode.decoder
|
||||
import cpu.pipeline.fetch.InstFifo
|
||||
|
||||
// class Core(implicit val config: CpuConfig) extends Module {
|
||||
// val io = IO(new Bundle {
|
||||
// val ext_int = Input(UInt(6.W))
|
||||
// val inst = new Cache_ICache()
|
||||
// val data = new Cache_DCache()
|
||||
// val debug = new DEBUG()
|
||||
// val statistic = if (!config.build) Some(new CPUStatistic()) else None
|
||||
// })
|
||||
class Core(implicit val config: CpuConfig) extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val ext_int = Input(UInt(6.W))
|
||||
val inst = new Cache_ICache()
|
||||
val data = new Cache_DCache()
|
||||
val debug = new DEBUG()
|
||||
})
|
||||
|
||||
// val ctrl = Module(new Ctrl()).io
|
||||
// val fetchUnit = Module(new FetchUnit()).io
|
||||
// val bpu = Module(new BranchPredictorUnit()).io
|
||||
// val instFifo = Module(new InstFifo()).io
|
||||
// val decoderUnit = Module(new DecoderUnit()).io
|
||||
// val regfile = Module(new ARegFile()).io
|
||||
// val executeStage = Module(new ExecuteStage()).io
|
||||
// val executeUnit = Module(new ExecuteUnit()).io
|
||||
// val cp0 = Module(new Cp0()).io
|
||||
// val memoryStage = Module(new MemoryStage()).io
|
||||
// val memoryUnit = Module(new MemoryUnit()).io
|
||||
// val writeBackStage = Module(new WriteBackStage()).io
|
||||
// val writeBackUnit = Module(new WriteBackUnit()).io
|
||||
val ctrl = Module(new Ctrl()).io
|
||||
val fetchUnit = Module(new FetchUnit()).io
|
||||
val bpu = Module(new BranchPredictorUnit()).io
|
||||
val instFifo = Module(new InstFifo()).io
|
||||
val decoderUnit = Module(new DecoderUnit()).io
|
||||
val regfile = Module(new ARegFile()).io
|
||||
val executeStage = Module(new ExecuteStage()).io
|
||||
val executeUnit = Module(new ExecuteUnit()).io
|
||||
val csr = Module(new Csr()).io
|
||||
val memoryStage = Module(new MemoryStage()).io
|
||||
val memoryUnit = Module(new MemoryUnit()).io
|
||||
val writeBackStage = Module(new WriteBackStage()).io
|
||||
val writeBackUnit = Module(new WriteBackUnit()).io
|
||||
|
||||
// ctrl.instFifo.has2insts := !(instFifo.empty || instFifo.almost_empty)
|
||||
// ctrl.decoderUnit <> decoderUnit.ctrl
|
||||
// ctrl.executeUnit <> executeUnit.ctrl
|
||||
// ctrl.memoryUnit <> memoryUnit.ctrl
|
||||
// ctrl.writeBackUnit <> writeBackUnit.ctrl
|
||||
// ctrl.cacheCtrl.iCache_stall := io.inst.icache_stall
|
||||
// ctrl.cacheCtrl.dCache_stall := io.data.dcache_stall
|
||||
ctrl.instFifo.has2insts := !(instFifo.empty || instFifo.almost_empty)
|
||||
ctrl.decoderUnit <> decoderUnit.ctrl
|
||||
ctrl.executeUnit <> executeUnit.ctrl
|
||||
ctrl.memoryUnit <> memoryUnit.ctrl
|
||||
ctrl.writeBackUnit <> writeBackUnit.ctrl
|
||||
ctrl.cacheCtrl.iCache_stall := io.inst.stall
|
||||
ctrl.cacheCtrl.dCache_stall := io.data.stall
|
||||
|
||||
// fetchUnit.memory <> memoryUnit.fetchUnit
|
||||
// fetchUnit.execute <> executeUnit.fetchUnit
|
||||
// fetchUnit.decoder <> decoderUnit.fetchUnit
|
||||
// fetchUnit.instFifo.full := instFifo.full
|
||||
// fetchUnit.iCache.inst_valid := io.inst.inst_valid
|
||||
// io.inst.addr(0) := fetchUnit.iCache.pc
|
||||
// io.inst.addr(1) := fetchUnit.iCache.pc_next
|
||||
// for (i <- 2 until config.instFetchNum) {
|
||||
// io.inst.addr(i) := fetchUnit.iCache.pc_next + ((i - 1) * 4).U
|
||||
// }
|
||||
fetchUnit.memory <> memoryUnit.fetchUnit
|
||||
fetchUnit.execute <> executeUnit.fetchUnit
|
||||
fetchUnit.decoder <> decoderUnit.fetchUnit
|
||||
fetchUnit.instFifo.full := instFifo.full
|
||||
fetchUnit.iCache.inst_valid := io.inst.valid
|
||||
io.inst.addr(0) := fetchUnit.iCache.pc
|
||||
io.inst.addr(1) := fetchUnit.iCache.pc_next
|
||||
for (i <- 2 until config.instFetchNum) {
|
||||
io.inst.addr(i) := fetchUnit.iCache.pc_next + ((i - 1) * 4).U
|
||||
}
|
||||
|
||||
// bpu.decoder.ena := ctrl.decoderUnit.allow_to_go
|
||||
// bpu.decoder.op := decoderUnit.bpu.decoded_inst0.op
|
||||
// bpu.decoder.inst := decoderUnit.bpu.decoded_inst0.inst
|
||||
// bpu.decoder.rs1 := decoderUnit.bpu.decoded_inst0.reg1_raddr
|
||||
// bpu.decoder.rs2 := decoderUnit.bpu.decoded_inst0.reg2_raddr
|
||||
// bpu.decoder.pc := decoderUnit.bpu.pc
|
||||
// bpu.decoder.pc_plus4 := decoderUnit.bpu.pc + 4.U
|
||||
// bpu.decoder.pht_index := decoderUnit.bpu.pht_index
|
||||
// decoderUnit.bpu.update_pht_index := bpu.decoder.update_pht_index
|
||||
// bpu.execute <> executeUnit.bpu
|
||||
// if (config.branchPredictor == "pesudo") {
|
||||
// bpu.regfile.get <> regfile.bpu.get
|
||||
// }
|
||||
// decoderUnit.bpu.branch_inst := bpu.decoder.branch_inst
|
||||
// decoderUnit.bpu.pred_branch := bpu.decoder.pred_branch
|
||||
// decoderUnit.bpu.branch_target := bpu.decoder.branch_target
|
||||
bpu.decoder.ena := ctrl.decoderUnit.allow_to_go
|
||||
bpu.decoder.op := decoderUnit.bpu.decoded_inst0.op
|
||||
bpu.decoder.inst := decoderUnit.bpu.decoded_inst0.inst
|
||||
bpu.decoder.rs1 := decoderUnit.bpu.decoded_inst0.reg1_raddr
|
||||
bpu.decoder.rs2 := decoderUnit.bpu.decoded_inst0.reg2_raddr
|
||||
bpu.decoder.pc := decoderUnit.bpu.pc
|
||||
bpu.decoder.pc_plus4 := decoderUnit.bpu.pc + 4.U
|
||||
bpu.decoder.pht_index := decoderUnit.bpu.pht_index
|
||||
decoderUnit.bpu.update_pht_index := bpu.decoder.update_pht_index
|
||||
bpu.execute <> executeUnit.bpu
|
||||
if (config.branchPredictor == "pesudo") {
|
||||
bpu.regfile.get <> regfile.bpu.get
|
||||
}
|
||||
decoderUnit.bpu.branch_inst := bpu.decoder.branch_inst
|
||||
decoderUnit.bpu.pred_branch := bpu.decoder.pred_branch
|
||||
decoderUnit.bpu.branch_target := bpu.decoder.branch_target
|
||||
|
||||
// instFifo.do_flush := ctrl.decoderUnit.do_flush
|
||||
// instFifo.icache_stall := io.inst.icache_stall
|
||||
// instFifo.jump_branch_inst := decoderUnit.instFifo.jump_branch_inst
|
||||
// instFifo.ren <> decoderUnit.instFifo.allow_to_go
|
||||
// decoderUnit.instFifo.inst <> instFifo.read
|
||||
instFifo.do_flush := ctrl.decoderUnit.do_flush
|
||||
instFifo.icache_stall := io.inst.stall
|
||||
instFifo.ren <> decoderUnit.instFifo.allow_to_go
|
||||
decoderUnit.instFifo.inst <> instFifo.read
|
||||
|
||||
// for (i <- 0 until config.instFetchNum) {
|
||||
// instFifo.write(i).pht_index := bpu.instBuffer.pht_index(i)
|
||||
// bpu.instBuffer.pc(i) := instFifo.write(i).pc
|
||||
// instFifo.wen(i) := io.inst.inst_valid(i)
|
||||
// instFifo.write(i).pc := io.inst.addr(0) + (i * 4).U
|
||||
// instFifo.write(i).inst := io.inst.inst(i)
|
||||
// }
|
||||
for (i <- 0 until config.instFetchNum) {
|
||||
instFifo.write(i).pht_index := bpu.instBuffer.pht_index(i)
|
||||
bpu.instBuffer.pc(i) := instFifo.write(i).pc
|
||||
instFifo.wen(i) := io.inst.valid(i)
|
||||
instFifo.write(i).pc := io.inst.addr(0) + (i * 4).U
|
||||
instFifo.write(i).inst := io.inst.rdata
|
||||
}
|
||||
|
||||
// decoderUnit.instFifo.info.empty := instFifo.empty
|
||||
// decoderUnit.instFifo.info.almost_empty := instFifo.almost_empty
|
||||
// decoderUnit.regfile <> regfile.read
|
||||
// for (i <- 0 until (config.fuNum)) {
|
||||
// decoderUnit.forward(i).exe := executeUnit.decoderUnit.forward(i).exe
|
||||
// decoderUnit.forward(i).mem_wreg := executeUnit.decoderUnit.forward(i).exe_mem_wreg
|
||||
// decoderUnit.forward(i).mem := memoryUnit.decoderUnit(i)
|
||||
// }
|
||||
// decoderUnit.cp0 <> cp0.decoderUnit
|
||||
// decoderUnit.executeStage <> executeStage.decoderUnit
|
||||
decoderUnit.instFifo.info.empty := instFifo.empty
|
||||
decoderUnit.instFifo.info.almost_empty := instFifo.almost_empty
|
||||
decoderUnit.regfile <> regfile.read
|
||||
for (i <- 0 until (config.fuNum)) {
|
||||
decoderUnit.forward(i).exe := executeUnit.decoderUnit.forward(i).exe
|
||||
decoderUnit.forward(i).mem_wreg := executeUnit.decoderUnit.forward(i).exe_mem_wreg
|
||||
decoderUnit.forward(i).mem := memoryUnit.decoderUnit(i)
|
||||
}
|
||||
decoderUnit.csr <> csr.decoderUnit
|
||||
decoderUnit.executeStage <> executeStage.decoderUnit
|
||||
|
||||
// executeStage.ctrl.clear(0) := ctrl.memoryUnit.flush_req ||
|
||||
// !decoderUnit.executeStage.inst0.ex.bd && ctrl.executeUnit.do_flush && ctrl.executeUnit.allow_to_go ||
|
||||
// !ctrl.decoderUnit.allow_to_go && ctrl.executeUnit.allow_to_go
|
||||
// executeStage.ctrl.clear(1) := ctrl.memoryUnit.flush_req ||
|
||||
// (ctrl.executeUnit.do_flush && decoderUnit.executeStage.inst1.allow_to_go) ||
|
||||
// (ctrl.executeUnit.allow_to_go && !decoderUnit.executeStage.inst1.allow_to_go)
|
||||
// executeStage.ctrl.inst0_allow_to_go := ctrl.executeUnit.allow_to_go
|
||||
executeStage.ctrl.clear(0) := ctrl.memoryUnit.flush_req ||
|
||||
!decoderUnit.executeStage.inst0.ex.bd && ctrl.executeUnit.do_flush && ctrl.executeUnit.allow_to_go ||
|
||||
!ctrl.decoderUnit.allow_to_go && ctrl.executeUnit.allow_to_go
|
||||
executeStage.ctrl.clear(1) := ctrl.memoryUnit.flush_req ||
|
||||
(ctrl.executeUnit.do_flush && decoderUnit.executeStage.inst1.allow_to_go) ||
|
||||
(ctrl.executeUnit.allow_to_go && !decoderUnit.executeStage.inst1.allow_to_go)
|
||||
executeStage.ctrl.inst0_allow_to_go := ctrl.executeUnit.allow_to_go
|
||||
|
||||
// executeUnit.decoderUnit.inst0_bd := decoderUnit.executeStage.inst0.ex.bd
|
||||
// executeUnit.executeStage <> executeStage.executeUnit
|
||||
// executeUnit.cp0 <> cp0.executeUnit
|
||||
// executeUnit.memoryStage <> memoryStage.executeUnit
|
||||
executeUnit.decoderUnit.inst0_bd := decoderUnit.executeStage.inst0.ex.bd
|
||||
executeUnit.executeStage <> executeStage.executeUnit
|
||||
executeUnit.csr <> csr.executeUnit
|
||||
executeUnit.memoryStage <> memoryStage.executeUnit
|
||||
|
||||
// cp0.ctrl.exe_stall := !ctrl.executeUnit.allow_to_go
|
||||
// cp0.ctrl.mem_stall := !ctrl.memoryUnit.allow_to_go
|
||||
// cp0.ext_int := io.ext_int
|
||||
memoryStage.ctrl.allow_to_go := ctrl.memoryUnit.allow_to_go
|
||||
memoryStage.ctrl.clear := ctrl.memoryUnit.do_flush
|
||||
|
||||
memoryUnit.memoryStage <> memoryStage.memoryUnit
|
||||
memoryUnit.csr <> csr.memoryUnit
|
||||
memoryUnit.writeBackStage <> writeBackStage.memoryUnit
|
||||
|
||||
// memoryStage.ctrl.allow_to_go := ctrl.memoryUnit.allow_to_go
|
||||
// memoryStage.ctrl.clear := ctrl.memoryUnit.do_flush
|
||||
csr.ctrl.exe_stall := !ctrl.executeUnit.allow_to_go
|
||||
csr.ctrl.mem_stall := !ctrl.memoryUnit.allow_to_go
|
||||
csr.ext_int := io.ext_int
|
||||
|
||||
// memoryUnit.memoryStage <> memoryStage.memoryUnit
|
||||
// memoryUnit.cp0 <> cp0.memoryUnit
|
||||
// memoryUnit.writeBackStage <> writeBackStage.memoryUnit
|
||||
memoryUnit.dataMemory.in.rdata := io.data.rdata
|
||||
io.data.en := memoryUnit.dataMemory.out.en
|
||||
io.data.size := memoryUnit.dataMemory.out.rlen
|
||||
io.data.write := memoryUnit.dataMemory.out.wen
|
||||
io.data.wdata := memoryUnit.dataMemory.out.wdata
|
||||
io.data.addr := memoryUnit.dataMemory.out.addr
|
||||
|
||||
// memoryUnit.dataMemory.in.rdata := io.data.rdata
|
||||
// io.data.en := memoryUnit.dataMemory.out.en
|
||||
// io.data.rlen := memoryUnit.dataMemory.out.rlen
|
||||
// io.data.wen := memoryUnit.dataMemory.out.wen
|
||||
// io.data.wdata := memoryUnit.dataMemory.out.wdata
|
||||
// io.data.addr := memoryUnit.dataMemory.out.addr
|
||||
writeBackStage.memoryUnit <> memoryUnit.writeBackStage
|
||||
writeBackStage.ctrl.allow_to_go := ctrl.writeBackUnit.allow_to_go
|
||||
writeBackStage.ctrl.clear := ctrl.writeBackUnit.do_flush
|
||||
|
||||
// writeBackStage.memoryUnit <> memoryUnit.writeBackStage
|
||||
// writeBackStage.ctrl.allow_to_go := ctrl.writeBackUnit.allow_to_go
|
||||
// writeBackStage.ctrl.clear := ctrl.writeBackUnit.do_flush
|
||||
writeBackUnit.writeBackStage <> writeBackStage.writeBackUnit
|
||||
writeBackUnit.ctrl <> ctrl.writeBackUnit
|
||||
regfile.write <> writeBackUnit.regfile
|
||||
|
||||
// writeBackUnit.writeBackStage <> writeBackStage.writeBackUnit
|
||||
// writeBackUnit.ctrl <> ctrl.writeBackUnit
|
||||
// regfile.write <> writeBackUnit.regfile
|
||||
io.debug <> writeBackUnit.debug
|
||||
|
||||
// io.debug <> writeBackUnit.debug
|
||||
|
||||
// io.inst.fence := executeUnit.executeStage.inst0.inst_info.ifence
|
||||
// io.inst.fence_addr := executeUnit.executeStage.inst0.inst_info.mem_addr
|
||||
// io.data.fence := memoryUnit.memoryStage.inst0.inst_info.dfence
|
||||
// io.data.fence_addr := memoryUnit.memoryStage.inst0.inst_info.mem_addr
|
||||
// io.data.execute_addr := executeUnit.memoryStage.inst0.mem.addr
|
||||
// io.inst.req := !instFifo.full
|
||||
// io.inst.cpu_stall := !ctrl.fetchUnit.allow_to_go
|
||||
// io.data.cpu_stall := !ctrl.memoryUnit.allow_to_go
|
||||
|
||||
// // ===----------------------------------------------------------------===
|
||||
// // statistic
|
||||
// // ===----------------------------------------------------------------===
|
||||
// if (!config.build) {
|
||||
// io.statistic.get.soc <> writeBackUnit.statistic.get
|
||||
// io.statistic.get.bpu <> executeUnit.statistic.get
|
||||
// }
|
||||
// }
|
||||
// io.inst.fence_i := executeUnit.executeStage.inst0.inst_info.ifence
|
||||
// io.data.fence_i := memoryUnit.memoryStage.inst0.inst_info.dfence
|
||||
io.inst.en := !instFifo.full
|
||||
io.inst.ready := !ctrl.fetchUnit.allow_to_go
|
||||
io.data.ready := !ctrl.memoryUnit.allow_to_go
|
||||
}
|
||||
|
|
|
@ -5,12 +5,11 @@ import chisel3.util._
|
|||
case class CpuConfig(
|
||||
val build: Boolean = false, // 是否为build模式
|
||||
val hasCommitBuffer: Boolean = false, // 是否有提交缓存
|
||||
val decoderNum: Int = 2, // 同时访问寄存器的指令数
|
||||
val commitNum: Int = 2, // 同时提交的指令数
|
||||
val fuNum: Int = 2, // 功能单元数
|
||||
val instFetchNum: Int = 2, // iCache取到的指令数量
|
||||
val decoderNum: Int = 1, // 同时访问寄存器的指令数
|
||||
val commitNum: Int = 1, // 同时提交的指令数
|
||||
val fuNum: Int = 1, // 功能单元数
|
||||
val instFetchNum: Int = 1, // iCache取到的指令数量
|
||||
val instFifoDepth: Int = 8, // 指令缓存深度
|
||||
val writeBufferDepth: Int = 16, // 写缓存深度
|
||||
val mulClockNum: Int = 2, // 乘法器的时钟周期数
|
||||
val divClockNum: Int = 8, // 除法器的时钟周期数
|
||||
val branchPredictor: String = "adaptive",// adaptive, pesudo, global
|
||||
|
@ -20,29 +19,3 @@ case class BranchPredictorConfig(
|
|||
val bhtDepth: Int = 5,
|
||||
val phtDepth: Int = 6,
|
||||
)
|
||||
|
||||
case class CacheConfig(
|
||||
nway: Int = 2, // 路数
|
||||
nbank: Int = 8, // bank数
|
||||
nset: Int,
|
||||
bankWidth: Int, // bytes per bank
|
||||
) {
|
||||
val config = CpuConfig()
|
||||
val indexWidth = log2Ceil(nset) // 6
|
||||
val bankIndexWidth = log2Ceil(nbank) // 3
|
||||
val bankOffsetWidth = log2Ceil(bankWidth) // 3
|
||||
val offsetWidth = bankIndexWidth + bankOffsetWidth // 6
|
||||
val tagWidth = 32 - indexWidth - offsetWidth // 20
|
||||
val tagvWidth = tagWidth + 1 // 21
|
||||
val bankWidthBits = bankWidth * 8 // 64
|
||||
val burstSize = 16
|
||||
val ninst = config.instFetchNum // TODO:改成可随意修改的参数
|
||||
require(isPow2(nset))
|
||||
require(isPow2(nway))
|
||||
require(isPow2(nbank))
|
||||
require(isPow2(bankWidth))
|
||||
require(
|
||||
tagWidth + indexWidth + bankIndexWidth + bankOffsetWidth == 32,
|
||||
"basic request calculation",
|
||||
)
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ class PuaCpu extends Module {
|
|||
val ext_int = Input(UInt(6.W))
|
||||
val axi = new AXI()
|
||||
val debug = new DEBUG()
|
||||
val statistic = if (!config.build) Some(new GlobalStatistic()) else None
|
||||
})
|
||||
val core = Module(new Core())
|
||||
val cache = Module(new Cache())
|
||||
|
|
|
@ -4,7 +4,6 @@ package cache
|
|||
import chisel3._
|
||||
import chisel3.util._
|
||||
import memory._
|
||||
import cpu.CacheConfig
|
||||
import cpu.defines._
|
||||
import cpu.CpuConfig
|
||||
import cpu.defines.Const._
|
||||
|
@ -61,6 +60,7 @@ class DCache(implicit config: CpuConfig) extends Module {
|
|||
io.axi.ar.lock := 0.U
|
||||
io.axi.r.ready := true.B
|
||||
io.cpu.rdata := 0.U
|
||||
io.cpu.stall := false.B
|
||||
|
||||
io.cpu.acc_err := false.B
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ class ICache(implicit config: CpuConfig) extends Module {
|
|||
io.axi.r.ready := true.B
|
||||
io.cpu.rdata := 0.U
|
||||
io.cpu.acc_err := false.B
|
||||
io.cpu.stall := false.B
|
||||
|
||||
switch(status) {
|
||||
is(s_idle) {
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
package cache.memory
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import cpu.CacheConfig
|
||||
import cpu.CpuConfig
|
||||
|
||||
/** LUT ram for XPM, one port for read/write, one port for read
|
||||
* @param depth
|
||||
* how many lines there are in the bank
|
||||
* @param width
|
||||
* how wide in bits each line is
|
||||
* @param config
|
||||
* implicit configuration to control generate ram for simulation or elaboration
|
||||
*/
|
||||
class LUTRam(depth: Int, width: Int)(implicit val config: CpuConfig) extends Module {
|
||||
require(isPow2(depth))
|
||||
val waddridth = log2Ceil(depth)
|
||||
val io = IO(new Bundle {
|
||||
val raddr = Input(UInt(waddridth.W))
|
||||
val rdata = Output(UInt(width.W))
|
||||
|
||||
val waddr = Input(UInt(waddridth.W))
|
||||
val wdata = Input(UInt(width.W))
|
||||
val wen = Input(Bool())
|
||||
val writeOutput = Output(UInt(width.W))
|
||||
})
|
||||
|
||||
if (config.build) {
|
||||
val bank = Module(
|
||||
new LUTRamIP(
|
||||
wdataidth = width,
|
||||
waddridth = waddridth,
|
||||
byteWriteWidth = width,
|
||||
numberOfLines = depth,
|
||||
),
|
||||
)
|
||||
bank.io.clka := clock
|
||||
bank.io.clkb := clock
|
||||
bank.io.rsta := reset
|
||||
bank.io.rstb := reset
|
||||
|
||||
bank.io.regcea := false.B
|
||||
bank.io.regceb := false.B
|
||||
bank.io.ena := true.B
|
||||
bank.io.enb := true.B
|
||||
|
||||
bank.io.addra := io.waddr
|
||||
bank.io.wea := io.wen
|
||||
bank.io.dina := io.wdata
|
||||
io.writeOutput := DontCare
|
||||
|
||||
bank.io.addrb := io.raddr
|
||||
io.rdata := bank.io.doutb
|
||||
} else {
|
||||
val bank = RegInit(VecInit(Seq.fill(depth)(0.U(width.W))))
|
||||
io.rdata := bank(io.raddr)
|
||||
io.writeOutput := DontCare
|
||||
when(io.wen) {
|
||||
bank(io.waddr) := io.wdata
|
||||
}.otherwise {
|
||||
io.writeOutput := bank(io.waddr)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
package cache.memory
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util.log2Ceil
|
||||
|
||||
/** XPM 2019.2 XPM_MEMORY_DPDISTRAM, at page 124 of UG953(2019.2) by default, this is initialized to
|
||||
* all 0
|
||||
*
|
||||
* @param wdataidth
|
||||
* : the size of the data to store in each line, in bits
|
||||
* @param waddridth
|
||||
* : the width of request
|
||||
* @param byteWriteWidth
|
||||
* : addressable size of write
|
||||
* @param numberOfLines
|
||||
* : how many **bits** there are in the memory
|
||||
*/
|
||||
class LUTRamIP(wdataidth: Int, waddridth: Int, byteWriteWidth: Int, numberOfLines: Int)
|
||||
extends BlackBox(
|
||||
Map(
|
||||
"ADDR_WIDTH_A" -> waddridth,
|
||||
"ADDR_WIDTH_B" -> waddridth,
|
||||
"MEMORY_SIZE" -> numberOfLines * wdataidth,
|
||||
"WRITE_DATA_WIDTH_A" -> wdataidth,
|
||||
"READ_DATA_WIDTH_A" -> wdataidth,
|
||||
"READ_DATA_WIDTH_B" -> wdataidth,
|
||||
"BYTE_WRITE_WIDTH_A" -> byteWriteWidth,
|
||||
"READ_LATENCY_A" -> 0,
|
||||
"READ_LATENCY_B" -> 0,
|
||||
"READ_RESET_VALUE_A" -> 0,
|
||||
"READ_RESET_VALUE_B" -> 0,
|
||||
"CLOCKING_MODE" -> "common_clock",
|
||||
),
|
||||
) {
|
||||
override def desiredName: String = "xpm_memory_dpdistram"
|
||||
require(
|
||||
waddridth == log2Ceil(numberOfLines),
|
||||
"request width should be log 2 of number of lines to request all",
|
||||
)
|
||||
require(
|
||||
wdataidth - (wdataidth / byteWriteWidth) * byteWriteWidth == 0,
|
||||
"data width should be a multiple of byte write width",
|
||||
)
|
||||
require(waddridth <= 20, "request width should be 1 to 20")
|
||||
val io = IO(new Bundle {
|
||||
val clka = Input(Clock())
|
||||
val clkb = Input(Clock())
|
||||
val rsta = Input(Reset())
|
||||
val rstb = Input(Reset())
|
||||
|
||||
val ena = Input(Bool())
|
||||
val enb = Input(Bool())
|
||||
val regcea = Input(Bool())
|
||||
val regceb = Input(Bool())
|
||||
|
||||
val dina = Input(UInt(wdataidth.W))
|
||||
val addra = Input(UInt(waddridth.W))
|
||||
val addrb = Input(UInt(waddridth.W))
|
||||
|
||||
val wea = Input(UInt((wdataidth / byteWriteWidth).W))
|
||||
|
||||
val douta = Output(UInt(wdataidth.W))
|
||||
val doutb = Output(UInt(wdataidth.W))
|
||||
})
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package cache.memory
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import cpu.CacheConfig
|
||||
|
||||
class ReadOnlyPort[+T <: Data](gen: T)(implicit cacheConfig: CacheConfig) extends Bundle {
|
||||
val addr = Input(UInt(log2Ceil(cacheConfig.nset * cacheConfig.nbank).W))
|
||||
val data = Output(gen)
|
||||
}
|
||||
|
||||
class WriteOnlyPort[+T <: Data](gen: T)(implicit cacheConfig: CacheConfig) extends Bundle {
|
||||
val addr = Input(UInt(log2Ceil(cacheConfig.nset * cacheConfig.nbank).W))
|
||||
val en = Input(Bool())
|
||||
val data = Input(gen)
|
||||
}
|
||||
|
||||
class WriteOnlyMaskPort[+T <: Data](gen: T)(implicit cacheConfig: CacheConfig) extends Bundle {
|
||||
val addr = Input(UInt(log2Ceil(cacheConfig.nset * cacheConfig.nbank).W))
|
||||
val en = Input(UInt(cacheConfig.bankWidth.W))
|
||||
val data = Input(gen)
|
||||
}
|
||||
|
||||
|
||||
class ReadWritePort[+T <: Data](gen: T)(implicit cacheConfig: CacheConfig) extends Bundle {
|
||||
val addr = Input(UInt(log2Ceil(cacheConfig.nset * cacheConfig.nbank).W))
|
||||
val en = Input(Bool())
|
||||
val wdata = Input(gen)
|
||||
val rdata = Output(gen)
|
||||
}
|
||||
|
||||
class MaskedReadWritePort[+T <: Data](gen: T)(implicit cacheConfig: CacheConfig) extends Bundle {
|
||||
val addr = Input(UInt(log2Ceil(cacheConfig.nset * cacheConfig.nbank).W))
|
||||
val writeMask = Input(UInt(cacheConfig.bankWidth.W))
|
||||
val wdata = Input(gen)
|
||||
val rdata = Output(gen)
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
package cache.memory
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import cpu.CpuConfig
|
||||
|
||||
/** simple dual port ram, with a port for reading and a port for writing
|
||||
*
|
||||
* @param depth
|
||||
* how many lines there are in the ram
|
||||
* @param width
|
||||
* how wide in bits each line is
|
||||
* @param byteAddressable
|
||||
* is it byte addressable?
|
||||
* @param cpuCfg
|
||||
* the implicit configuration for simulation and elaboration
|
||||
*/
|
||||
class SimpleDualPortRam(depth: Int, width: Int, byteAddressable: Boolean)(implicit
|
||||
val config: CpuConfig,
|
||||
) extends Module {
|
||||
require(isPow2(depth))
|
||||
require(
|
||||
width % 8 == 0 || !byteAddressable,
|
||||
"if memory is byte addressable, then the adderss width must be a multiple of 8",
|
||||
)
|
||||
val waddridth = log2Ceil(depth)
|
||||
|
||||
val io = IO(new Bundle {
|
||||
val raddr = Input(UInt(waddridth.W))
|
||||
val ren = Input(Bool())
|
||||
val rdata = Output(UInt(width.W))
|
||||
|
||||
val waddr = Input(UInt(waddridth.W))
|
||||
val wen = Input(Bool())
|
||||
val wstrb = Input(UInt((if (byteAddressable) width / 8 else 1).W))
|
||||
val wdata = Input(UInt(width.W))
|
||||
})
|
||||
|
||||
if (config.build) {
|
||||
val memory = Module(
|
||||
new SimpleDualPortRamIP(
|
||||
wdataidth = width,
|
||||
byteWriteWidth = if (byteAddressable) 8 else width,
|
||||
numberOfLines = depth,
|
||||
waddridth = waddridth,
|
||||
),
|
||||
)
|
||||
memory.io.clka := clock
|
||||
memory.io.clkb := clock
|
||||
memory.io.rstb := reset
|
||||
|
||||
memory.io.addra := io.waddr
|
||||
memory.io.ena := io.wen
|
||||
memory.io.dina := io.wdata
|
||||
memory.io.wea := io.wstrb
|
||||
|
||||
memory.io.addrb := io.raddr
|
||||
memory.io.enb := io.ren
|
||||
memory.io.regceb := false.B
|
||||
io.rdata := memory.io.doutb
|
||||
} else {
|
||||
assert(
|
||||
io.wstrb.orR || !io.wen,
|
||||
"when write port enable is high, write vector cannot be all 0",
|
||||
)
|
||||
if (byteAddressable) {
|
||||
val bank = SyncReadMem(depth, Vec(width / 8, UInt(8.W)))
|
||||
when(io.ren) {
|
||||
io.rdata := bank(io.raddr).asTypeOf(io.rdata)
|
||||
}.otherwise {
|
||||
io.rdata := DontCare
|
||||
}
|
||||
when(io.wen) {
|
||||
bank.write(io.waddr, io.wdata.asTypeOf(Vec(width / 8, UInt(8.W))), io.wstrb.asBools)
|
||||
}
|
||||
} else {
|
||||
val bank = SyncReadMem(depth, UInt(width.W))
|
||||
|
||||
when(io.ren) {
|
||||
io.rdata := bank.read(io.raddr)
|
||||
}.otherwise {
|
||||
io.rdata := 0.U(32.W)
|
||||
}
|
||||
|
||||
when(io.wen) {
|
||||
bank.write(io.waddr, io.wdata)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
package cache.memory
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util.log2Ceil
|
||||
|
||||
/** simple dual port ram
|
||||
*
|
||||
* @param wdataidth
|
||||
* : width of every data line
|
||||
* @param byteWriteWidth
|
||||
* : how many bits to write per mask
|
||||
* @param numberOfLines
|
||||
* : how many lines of data are in the ram
|
||||
* @param waddridth
|
||||
* : how wide is the request (to cover all lines)
|
||||
* @param memoryPrimitive
|
||||
* : should I use auto, block ram or distributed ram
|
||||
*/
|
||||
class SimpleDualPortRamIP(
|
||||
wdataidth: Int = 32,
|
||||
byteWriteWidth: Int = 8,
|
||||
numberOfLines: Int,
|
||||
waddridth: Int,
|
||||
memoryPrimitive: String = "block",
|
||||
) extends BlackBox(
|
||||
Map(
|
||||
"ADDR_WIDTH_A" -> waddridth,
|
||||
"ADDR_WIDTH_B" -> waddridth,
|
||||
"WRITE_DATA_WIDTH_A" -> wdataidth,
|
||||
"READ_DATA_WIDTH_B" -> wdataidth,
|
||||
"BYTE_WRITE_WIDTH_A" -> byteWriteWidth,
|
||||
"CLOCKING_MODE" -> "common_clock",
|
||||
"READ_LATENCY_B" -> 1,
|
||||
"MEMORY_SIZE" -> numberOfLines * wdataidth,
|
||||
"MEMORY_PRIMITIVE" -> memoryPrimitive,
|
||||
),
|
||||
) {
|
||||
override def desiredName: String = "xpm_memory_sdpram"
|
||||
require(waddridth <= 20, "request width should be 1 to 20")
|
||||
require(
|
||||
wdataidth - (wdataidth / byteWriteWidth) * byteWriteWidth == 0,
|
||||
"data width should be a multiple of byte write width",
|
||||
)
|
||||
require(
|
||||
List("auto", "block", "distributed", "ultra").contains(memoryPrimitive),
|
||||
"memory primitive should be auto, block ram, dist ram or ultra ram",
|
||||
)
|
||||
require(
|
||||
waddridth == log2Ceil(numberOfLines),
|
||||
"request width should be log 2 of number of lines to request all",
|
||||
)
|
||||
val io = IO(new Bundle {
|
||||
// clock and reset
|
||||
val clka = Input(Clock())
|
||||
val clkb = Input(Clock())
|
||||
val rstb = Input(Reset())
|
||||
|
||||
val addra = Input(UInt(waddridth.W))
|
||||
val dina = Input(UInt(wdataidth.W))
|
||||
val ena = Input(Bool())
|
||||
val wea = Input(UInt((wdataidth / byteWriteWidth).W))
|
||||
|
||||
val addrb = Input(UInt(waddridth.W))
|
||||
val enb = Input(Bool())
|
||||
val regceb = Input(Bool())
|
||||
val doutb = Output(UInt(wdataidth.W))
|
||||
})
|
||||
}
|
|
@ -33,7 +33,7 @@ class InstInfo extends Bundle {
|
|||
val reg_wen = Bool()
|
||||
val reg_waddr = UInt(REG_ADDR_WID.W)
|
||||
val imm32 = UInt(DATA_WID.W)
|
||||
val cp0_addr = UInt(CP0_ADDR_WID.W)
|
||||
val csr_addr = UInt(CSR_ADDR_WID.W)
|
||||
val dual_issue = Bool()
|
||||
val whilo = Bool()
|
||||
val rmem = Bool()
|
||||
|
@ -125,6 +125,7 @@ class Cache_ICache(implicit val config: CpuConfig) extends Bundle {
|
|||
val rdata = Input(UInt(INST_WID.W))
|
||||
val valid = Input(Bool())
|
||||
val acc_err = Input(Bool())
|
||||
val stall = Input(Bool())
|
||||
}
|
||||
|
||||
// cpu to dcache
|
||||
|
@ -140,6 +141,7 @@ class Cache_DCache extends Bundle {
|
|||
val rdata = Input(UInt(DATA_WID.W))
|
||||
val valid = Input(Bool())
|
||||
val acc_err = Input(Bool())
|
||||
val stall = Input(Bool())
|
||||
}
|
||||
|
||||
// axi
|
||||
|
|
|
@ -49,7 +49,7 @@ trait Constants {
|
|||
val EXE_MTHI = 14.U(OP_WID.W)
|
||||
val EXE_MFLO = 15.U(OP_WID.W)
|
||||
val EXE_MTLO = 16.U(OP_WID.W)
|
||||
// CP0 Move
|
||||
// CSR Move
|
||||
val EXE_MFC0 = 17.U(OP_WID.W)
|
||||
val EXE_MTC0 = 18.U(OP_WID.W)
|
||||
// 比较
|
||||
|
@ -155,44 +155,44 @@ trait Constants {
|
|||
val REG_ADDR_WID = 5
|
||||
val DATA_WID = XLEN
|
||||
|
||||
// CP0寄存器
|
||||
// CP0 Register (5.w), Select (3.w)
|
||||
val CP0_INDEX_ADDR = "b00000_000".U(8.W) // 0,0
|
||||
val CP0_RANDOM_ADDR = "b00001_000".U(8.W) // 1,0
|
||||
val CP0_ENTRYLO0_ADDR = "b00010_000".U(8.W) // 2,0
|
||||
val CP0_ENTRYLO1_ADDR = "b00011_000".U(8.W) // 3,0
|
||||
val CP0_CONTEXT_ADDR = "b00100_000".U(8.W) // 4,0
|
||||
// val CP0_CONTEXT_CONFIG_ADDR = "b00100_001".U(8.W) // 4,1
|
||||
// val CP0_USER_LOCAL_ADDR = "b00100_010".U(8.W) // 4,2
|
||||
val CP0_PAGE_MASK_ADDR = "b00101_000".U(8.W) // 5,0
|
||||
// val CP0_PAGE_GRAIN_ADDR = "b00101_001".U(8.W) // 5,1
|
||||
val CP0_WIRED_ADDR = "b00110_000".U(8.W) // 6,0
|
||||
// val CP0_HWRENA_ADDR = "b00111_000".U(8.W) // 7,0
|
||||
val CP0_BADV_ADDR = "b01000_000".U(8.W) // 8,0
|
||||
val CP0_COUNT_ADDR = "b01001_000".U(8.W) // 9,0 (sel保留 6or7)
|
||||
val CP0_ENTRYHI_ADDR = "b01010_000".U(8.W) // 10,0
|
||||
val CP0_COMPARE_ADDR = "b01011_000".U(8.W) // 11,0 (sel保留 6or7)
|
||||
val CP0_STATUS_ADDR = "b01100_000".U(8.W) // 12,0
|
||||
// val CP0_INTCTL_ADDR = "b01100_001".U(8.W) // 12,1
|
||||
// val CP0_SRSCTL_ADDR = "b01100_010".U(8.W) // 12,2
|
||||
// val CP0_SRSMAP_ADDR = "b01100_011".U(8.W) // 12,3
|
||||
val CP0_CAUSE_ADDR = "b01101_000".U(8.W) // 13,0
|
||||
val CP0_EPC_ADDR = "b01110_000".U(8.W) // 14,0
|
||||
val CP0_PRID_ADDR = "b01111_000".U(8.W) // 15,0
|
||||
val CP0_EBASE_ADDR = "b01111_001".U(8.W) // 15,1
|
||||
// val CP0_CDMMBASE_ADDR = "b01111_010".U(8.W) // 15,2
|
||||
// val CP0_CMGCRBASE_ADDR = "b01111_011".U(8.W) // 15,3
|
||||
val CP0_CONFIG_ADDR = "b10000_000".U(8.W) // 16,0
|
||||
val CP0_CONFIG1_ADDR = "b10000_001".U(8.W) // 16,1
|
||||
// val CP0_CONFIG2_ADDR = "b10000_010".U(8.W) // 16,2
|
||||
// val CP0_CONFIG3_ADDR = "b10000_011".U(8.W) // 16,3
|
||||
// val CP0_CONFIG4_ADDR = "b10000_100".U(8.W) // 16,4 (sel保留 6or7)
|
||||
// val CP0_LOAD_LINKED_ADDR = "b10001_000".U(8.W) // 17,0
|
||||
val CP0_TAGLO_ADDR = "b11100_000".U(8.W) // 28,0
|
||||
val CP0_TAGHI_ADDR = "b11101_000".U(8.W) // 29,0
|
||||
val CP0_ERROR_EPC_ADDR = "b11110_000".U(8.W) // 30,0
|
||||
// CSR寄存器
|
||||
// CSR Register (5.w), Select (3.w)
|
||||
val CSR_INDEX_ADDR = "b00000_000".U(8.W) // 0,0
|
||||
val CSR_RANDOM_ADDR = "b00001_000".U(8.W) // 1,0
|
||||
val CSR_ENTRYLO0_ADDR = "b00010_000".U(8.W) // 2,0
|
||||
val CSR_ENTRYLO1_ADDR = "b00011_000".U(8.W) // 3,0
|
||||
val CSR_CONTEXT_ADDR = "b00100_000".U(8.W) // 4,0
|
||||
// val CSR_CONTEXT_CONFIG_ADDR = "b00100_001".U(8.W) // 4,1
|
||||
// val CSR_USER_LOCAL_ADDR = "b00100_010".U(8.W) // 4,2
|
||||
val CSR_PAGE_MASK_ADDR = "b00101_000".U(8.W) // 5,0
|
||||
// val CSR_PAGE_GRAIN_ADDR = "b00101_001".U(8.W) // 5,1
|
||||
val CSR_WIRED_ADDR = "b00110_000".U(8.W) // 6,0
|
||||
// val CSR_HWRENA_ADDR = "b00111_000".U(8.W) // 7,0
|
||||
val CSR_BADV_ADDR = "b01000_000".U(8.W) // 8,0
|
||||
val CSR_COUNT_ADDR = "b01001_000".U(8.W) // 9,0 (sel保留 6or7)
|
||||
val CSR_ENTRYHI_ADDR = "b01010_000".U(8.W) // 10,0
|
||||
val CSR_COMPARE_ADDR = "b01011_000".U(8.W) // 11,0 (sel保留 6or7)
|
||||
val CSR_STATUS_ADDR = "b01100_000".U(8.W) // 12,0
|
||||
// val CSR_INTCTL_ADDR = "b01100_001".U(8.W) // 12,1
|
||||
// val CSR_SRSCTL_ADDR = "b01100_010".U(8.W) // 12,2
|
||||
// val CSR_SRSMAP_ADDR = "b01100_011".U(8.W) // 12,3
|
||||
val CSR_CAUSE_ADDR = "b01101_000".U(8.W) // 13,0
|
||||
val CSR_EPC_ADDR = "b01110_000".U(8.W) // 14,0
|
||||
val CSR_PRID_ADDR = "b01111_000".U(8.W) // 15,0
|
||||
val CSR_EBASE_ADDR = "b01111_001".U(8.W) // 15,1
|
||||
// val CSR_CDMMBASE_ADDR = "b01111_010".U(8.W) // 15,2
|
||||
// val CSR_CMGCRBASE_ADDR = "b01111_011".U(8.W) // 15,3
|
||||
val CSR_CONFIG_ADDR = "b10000_000".U(8.W) // 16,0
|
||||
val CSR_CONFIG1_ADDR = "b10000_001".U(8.W) // 16,1
|
||||
// val CSR_CONFIG2_ADDR = "b10000_010".U(8.W) // 16,2
|
||||
// val CSR_CONFIG3_ADDR = "b10000_011".U(8.W) // 16,3
|
||||
// val CSR_CONFIG4_ADDR = "b10000_100".U(8.W) // 16,4 (sel保留 6or7)
|
||||
// val CSR_LOAD_LINKED_ADDR = "b10001_000".U(8.W) // 17,0
|
||||
val CSR_TAGLO_ADDR = "b11100_000".U(8.W) // 28,0
|
||||
val CSR_TAGHI_ADDR = "b11101_000".U(8.W) // 29,0
|
||||
val CSR_ERROR_EPC_ADDR = "b11110_000".U(8.W) // 30,0
|
||||
|
||||
val CP0_ADDR_WID = 8
|
||||
val CSR_ADDR_WID = 8
|
||||
|
||||
val PTEBASE_WID = 9
|
||||
|
||||
|
|
|
@ -4,18 +4,18 @@ import chisel3._
|
|||
import chisel3.util._
|
||||
import cpu.defines.Const._
|
||||
|
||||
class Cp0Index extends Bundle {
|
||||
class CsrIndex extends Bundle {
|
||||
val p = Bool()
|
||||
val blank = UInt((32 - 1 - log2Ceil(TLB_NUM)).W)
|
||||
val index = UInt(log2Ceil(TLB_NUM).W)
|
||||
}
|
||||
|
||||
class Cp0Random extends Bundle {
|
||||
class CsrRandom extends Bundle {
|
||||
val blank = UInt((32 - log2Ceil(TLB_NUM)).W)
|
||||
val random = UInt(log2Ceil(TLB_NUM).W)
|
||||
}
|
||||
|
||||
class Cp0EntryLo extends Bundle {
|
||||
class CsrEntryLo extends Bundle {
|
||||
val fill = UInt((32 - PFN_WID - C_WID - 3).W)
|
||||
val pfn = UInt(PFN_WID.W)
|
||||
val c = UInt(C_WID.W)
|
||||
|
@ -24,36 +24,36 @@ class Cp0EntryLo extends Bundle {
|
|||
val g = Bool()
|
||||
}
|
||||
|
||||
class Cp0Context extends Bundle {
|
||||
class CsrContext extends Bundle {
|
||||
val ptebase = UInt(PTEBASE_WID.W)
|
||||
val badvpn2 = UInt(VPN2_WID.W)
|
||||
val blank = UInt((32 - PTEBASE_WID - VPN2_WID).W)
|
||||
}
|
||||
|
||||
class Cp0Wired extends Bundle {
|
||||
class CsrWired extends Bundle {
|
||||
val blank = UInt((31 - log2Ceil(TLB_NUM)).W)
|
||||
val wired = UInt(log2Ceil(TLB_NUM).W)
|
||||
}
|
||||
|
||||
class Cp0BadVAddr extends Bundle {
|
||||
class CsrBadVAddr extends Bundle {
|
||||
val badvaddr = UInt(PC_WID.W)
|
||||
}
|
||||
|
||||
class Cp0Count extends Bundle {
|
||||
class CsrCount extends Bundle {
|
||||
val count = UInt(DATA_WID.W)
|
||||
}
|
||||
|
||||
class Cp0EntryHi extends Bundle {
|
||||
class CsrEntryHi extends Bundle {
|
||||
val vpn2 = UInt(VPN2_WID.W)
|
||||
val blank = UInt((32 - VPN2_WID - ASID_WID).W)
|
||||
val asid = UInt(ASID_WID.W)
|
||||
}
|
||||
|
||||
class Cp0Compare extends Bundle {
|
||||
class CsrCompare extends Bundle {
|
||||
val compare = UInt(DATA_WID.W)
|
||||
}
|
||||
|
||||
class Cp0Status extends Bundle {
|
||||
class CsrStatus extends Bundle {
|
||||
val blank3 = UInt(3.W)
|
||||
val cu0 = Bool()
|
||||
val blank2 = UInt(5.W)
|
||||
|
@ -68,7 +68,7 @@ class Cp0Status extends Bundle {
|
|||
val ie = Bool()
|
||||
}
|
||||
|
||||
class Cp0Cause extends Bundle {
|
||||
class CsrCause extends Bundle {
|
||||
val bd = Bool()
|
||||
val blank3 = UInt(7.W)
|
||||
val iv = Bool()
|
||||
|
@ -79,11 +79,11 @@ class Cp0Cause extends Bundle {
|
|||
val blank0 = UInt(2.W)
|
||||
}
|
||||
|
||||
class Cp0Epc extends Bundle {
|
||||
class CsrEpc extends Bundle {
|
||||
val epc = UInt(PC_WID.W)
|
||||
}
|
||||
|
||||
class Cp0Ebase extends Bundle {
|
||||
class CsrEbase extends Bundle {
|
||||
val fill = Bool()
|
||||
val blank1 = Bool()
|
||||
val ebase = UInt(18.W)
|
||||
|
@ -91,7 +91,7 @@ class Cp0Ebase extends Bundle {
|
|||
val cpuNum = UInt(10.W)
|
||||
}
|
||||
|
||||
class Cp0Config extends Bundle {
|
||||
class CsrConfig extends Bundle {
|
||||
val m = Bool()
|
||||
val k23 = UInt(3.W)
|
||||
val ku = UInt(3.W)
|
||||
|
@ -105,7 +105,7 @@ class Cp0Config extends Bundle {
|
|||
val k0 = UInt(3.W)
|
||||
}
|
||||
|
||||
class Cp0Config1 extends Bundle {
|
||||
class CsrConfig1 extends Bundle {
|
||||
val m = Bool()
|
||||
val ms = UInt(6.W)
|
||||
val is = UInt(3.W)
|
||||
|
@ -123,6 +123,6 @@ class Cp0Config1 extends Bundle {
|
|||
val fp = Bool()
|
||||
}
|
||||
|
||||
class Cp0ErrorEpc extends Bundle {
|
||||
class CsrErrorEpc extends Bundle {
|
||||
val errorEpc = UInt(PC_WID.W)
|
||||
}
|
||||
|
|
|
@ -6,9 +6,9 @@ import cpu.defines.Const._
|
|||
import cpu.CpuConfig
|
||||
|
||||
class SocStatistic extends Bundle {
|
||||
val cp0_count = Output(UInt(32.W))
|
||||
val cp0_random = Output(UInt(32.W))
|
||||
val cp0_cause = Output(UInt(32.W))
|
||||
val csr_count = Output(UInt(32.W))
|
||||
val csr_random = Output(UInt(32.W))
|
||||
val csr_cause = Output(UInt(32.W))
|
||||
val int = Output(Bool())
|
||||
val commit = Output(Bool())
|
||||
}
|
||||
|
|
|
@ -177,7 +177,7 @@
|
|||
// IMM_HZE -> Cat(imm16, Fill(16, 0.U))
|
||||
// )
|
||||
// )
|
||||
// io.out.cp0_addr := Cat(inst(15, 11), inst(2, 0))
|
||||
// io.out.csr_addr := Cat(inst(15, 11), inst(2, 0))
|
||||
// io.out.dual_issue := dual_issue
|
||||
// io.out.whilo := VecInit(FU_MUL, FU_DIV, FU_MTHILO).contains(fusel) && op =/= EXE_MUL // MUL不写HILO
|
||||
// io.out.inst := inst
|
||||
|
|
|
@ -15,8 +15,6 @@ class InstFifoDecoderUnit(implicit val config: CpuConfig) extends Bundle {
|
|||
val empty = Bool()
|
||||
val almost_empty = Bool()
|
||||
})
|
||||
|
||||
val jump_branch_inst = Output(Bool())
|
||||
}
|
||||
|
||||
class DataForwardToDecoderUnit extends Bundle {
|
||||
|
@ -25,7 +23,7 @@ class DataForwardToDecoderUnit extends Bundle {
|
|||
val mem = new RegWrite()
|
||||
}
|
||||
|
||||
class Cp0DecoderUnit extends Bundle {
|
||||
class CsrDecoderUnit extends Bundle {
|
||||
val access_allowed = Bool()
|
||||
val kernel_mode = Bool()
|
||||
val intterupt_allowed = Bool()
|
||||
|
@ -39,7 +37,7 @@ class DecoderUnit(implicit val config: CpuConfig) extends Module {
|
|||
val instFifo = new InstFifoDecoderUnit()
|
||||
val regfile = Vec(config.decoderNum, new Src12Read())
|
||||
val forward = Input(Vec(config.fuNum, new DataForwardToDecoderUnit()))
|
||||
val cp0 = Input(new Cp0DecoderUnit())
|
||||
val csr = Input(new CsrDecoderUnit())
|
||||
// 输出
|
||||
val fetchUnit = new Bundle {
|
||||
val branch = Output(Bool())
|
||||
|
@ -83,7 +81,6 @@ class DecoderUnit(implicit val config: CpuConfig) extends Module {
|
|||
jumpCtrl.in.pc := io.instFifo.inst(0).pc
|
||||
jumpCtrl.in.reg1_data := io.regfile(0).src1.rdata
|
||||
|
||||
val jump_branch_inst0 = jumpCtrl.out.jump_inst || io.bpu.branch_inst
|
||||
val inst0_branch = jumpCtrl.out.jump || io.bpu.pred_branch
|
||||
|
||||
io.fetchUnit.branch := inst0_branch
|
||||
|
@ -91,7 +88,6 @@ class DecoderUnit(implicit val config: CpuConfig) extends Module {
|
|||
|
||||
io.instFifo.allow_to_go(0) := io.ctrl.allow_to_go
|
||||
io.instFifo.allow_to_go(1) := issue.inst1.allow_to_go
|
||||
io.instFifo.jump_branch_inst := jump_branch_inst0
|
||||
|
||||
io.bpu.id_allow_to_go := io.ctrl.allow_to_go
|
||||
io.bpu.pc := io.instFifo.inst(0).pc
|
||||
|
@ -107,7 +103,7 @@ class DecoderUnit(implicit val config: CpuConfig) extends Module {
|
|||
val pc = io.instFifo.inst.map(_.pc)
|
||||
val inst = io.instFifo.inst.map(_.inst)
|
||||
val inst_info = decoder.map(_.io.out)
|
||||
val interrupt = io.cp0.intterupt_allowed && (io.cp0.cause_ip & io.cp0.status_im).orR && !io.instFifo.info.empty
|
||||
val interrupt = io.csr.intterupt_allowed && (io.csr.cause_ip & io.csr.status_im).orR && !io.instFifo.info.empty
|
||||
|
||||
for (i <- 0 until (config.decoderNum)) {
|
||||
decoder(i).io.in.inst := inst(i)
|
||||
|
@ -142,13 +138,13 @@ class DecoderUnit(implicit val config: CpuConfig) extends Module {
|
|||
io.executeStage.inst0.ex.eret := inst_info(0).op === EXE_ERET
|
||||
io.executeStage.inst0.ex.badvaddr := pc(0)
|
||||
val inst0_ex_cpu =
|
||||
!io.cp0.access_allowed && VecInit(EXE_MFC0, EXE_MTC0, EXE_TLBR, EXE_TLBWI, EXE_TLBWR, EXE_TLBP, EXE_ERET, EXE_WAIT)
|
||||
!io.csr.access_allowed && VecInit(EXE_MFC0, EXE_MTC0, EXE_TLBR, EXE_TLBWI, EXE_TLBWR, EXE_TLBP, EXE_ERET, EXE_WAIT)
|
||||
.contains(inst_info(0).op)
|
||||
io.executeStage.inst0.ex.excode := MuxCase(
|
||||
EX_NO,
|
||||
Seq(
|
||||
interrupt -> EX_INT,
|
||||
(pc(0)(1, 0).orR || (pc(0)(31) && !io.cp0.kernel_mode)) -> EX_ADEL,
|
||||
(pc(0)(1, 0).orR || (pc(0)(31) && !io.csr.kernel_mode)) -> EX_ADEL,
|
||||
(inst_info(0).inst_valid === INST_INVALID) -> EX_RI,
|
||||
(inst_info(0).op === EXE_SYSCALL) -> EX_SYS,
|
||||
(inst_info(0).op === EXE_BREAK) -> EX_BP,
|
||||
|
@ -186,12 +182,12 @@ class DecoderUnit(implicit val config: CpuConfig) extends Module {
|
|||
io.executeStage.inst1.ex.eret := inst_info(1).op === EXE_ERET
|
||||
io.executeStage.inst1.ex.badvaddr := pc(1)
|
||||
val inst1_ex_cpu =
|
||||
!io.cp0.access_allowed && VecInit(EXE_MFC0, EXE_MTC0, EXE_TLBR, EXE_TLBWI, EXE_TLBWR, EXE_TLBP, EXE_ERET, EXE_WAIT)
|
||||
!io.csr.access_allowed && VecInit(EXE_MFC0, EXE_MTC0, EXE_TLBR, EXE_TLBWI, EXE_TLBWR, EXE_TLBP, EXE_ERET, EXE_WAIT)
|
||||
.contains(inst_info(1).op)
|
||||
io.executeStage.inst1.ex.excode := MuxCase(
|
||||
EX_NO,
|
||||
Seq(
|
||||
(pc(1)(1, 0).orR || (pc(1)(31) && !io.cp0.kernel_mode)) -> EX_ADEL,
|
||||
(pc(1)(1, 0).orR || (pc(1)(31) && !io.csr.kernel_mode)) -> EX_ADEL,
|
||||
(inst_info(1).inst_valid === INST_INVALID) -> EX_RI,
|
||||
(inst_info(1).op === EXE_SYSCALL) -> EX_SYS,
|
||||
(inst_info(1).op === EXE_BREAK) -> EX_BP,
|
||||
|
|
|
@ -44,9 +44,9 @@ class Issue(implicit val config: CpuConfig) extends Module {
|
|||
inst0.reg_wen && (inst0.reg_waddr === inst1.reg1_raddr && inst1.reg1_ren || inst0.reg_waddr === inst1.reg2_raddr && inst1.reg2_ren)
|
||||
val raw_hilo = VecInit(FU_DIV, FU_MUL, FU_MTHILO).contains(inst0.fusel) &&
|
||||
VecInit(FU_DIV, FU_MUL, FU_MFHILO, FU_MTHILO).contains(inst1.fusel)
|
||||
val raw_cp0 =
|
||||
inst0.op === EXE_MTC0 && inst1.op === EXE_MFC0 && inst0.cp0_addr === inst1.cp0_addr
|
||||
val data_conflict = raw_reg || raw_hilo || raw_cp0 || load_stall
|
||||
val raw_csr =
|
||||
inst0.op === EXE_MTC0 && inst1.op === EXE_MFC0 && inst0.csr_addr === inst1.csr_addr
|
||||
val data_conflict = raw_reg || raw_hilo || raw_csr || load_stall
|
||||
|
||||
// 指令1是否允许执行
|
||||
io.inst1.allow_to_go := io.allow_to_go &&
|
||||
|
|
|
@ -23,7 +23,7 @@ class Alu extends Module {
|
|||
val io = IO(new Bundle {
|
||||
val inst_info = Input(new InstInfo())
|
||||
val src_info = Input(new SrcInfo())
|
||||
val cp0_rdata = Input(UInt(DATA_WID.W))
|
||||
val csr_rdata = Input(UInt(DATA_WID.W))
|
||||
val llbit = Input(Bool())
|
||||
val hilo = new Bundle {
|
||||
val rdata = Input(UInt(HILO_WID.W))
|
||||
|
@ -100,7 +100,7 @@ class Alu extends Module {
|
|||
// 数据移动指令
|
||||
EXE_MFHI -> io.hilo.rdata(63, 32),
|
||||
EXE_MFLO -> io.hilo.rdata(31, 0),
|
||||
EXE_MFC0 -> io.cp0_rdata,
|
||||
EXE_MFC0 -> io.csr_rdata,
|
||||
EXE_MOVN -> src1,
|
||||
EXE_MOVZ -> src1,
|
||||
// 前导记数指令
|
||||
|
|
|
@ -1,453 +0,0 @@
|
|||
// package cpu.pipeline.execute
|
||||
|
||||
// import chisel3._
|
||||
// import chisel3.util._
|
||||
// import cpu.defines._
|
||||
// import cpu.defines.Const._
|
||||
// import cpu.pipeline.memory.Cp0Info
|
||||
// import cpu.CpuConfig
|
||||
// import cpu.pipeline.decoder.Cp0DecoderUnit
|
||||
|
||||
// class Cp0MemoryUnit(implicit val config: CpuConfig) extends Bundle {
|
||||
// val in = Input(new Bundle {
|
||||
// val inst = Vec(
|
||||
// config.fuNum,
|
||||
// new Bundle {
|
||||
// val pc = UInt(PC_WID.W)
|
||||
// val ex = new ExceptionInfo()
|
||||
// }
|
||||
// )
|
||||
// })
|
||||
// val out = Output(new Bundle {
|
||||
// val flush = Bool()
|
||||
// val flush_pc = UInt(PC_WID.W)
|
||||
// })
|
||||
// }
|
||||
|
||||
// class Cp0ExecuteUnit(implicit val config: CpuConfig) extends Bundle {
|
||||
// val in = Input(new Bundle {
|
||||
// val inst_info = Vec(config.fuNum, new InstInfo())
|
||||
// val mtc0_wdata = UInt(DATA_WID.W)
|
||||
// })
|
||||
// val out = Output(new Bundle {
|
||||
// val cp0_rdata = Vec(config.fuNum, UInt(DATA_WID.W))
|
||||
// val debug = Output(new Cp0Info())
|
||||
// })
|
||||
// }
|
||||
|
||||
// class Cp0(implicit val config: CpuConfig) extends Module {
|
||||
// val io = IO(new Bundle {
|
||||
// val ext_int = Input(UInt(EXT_INT_WID.W))
|
||||
// val ctrl = Input(new Bundle {
|
||||
// val exe_stall = Bool()
|
||||
// val mem_stall = Bool()
|
||||
// })
|
||||
// val decoderUnit = Output(new Cp0DecoderUnit())
|
||||
// val executeUnit = new Cp0ExecuteUnit()
|
||||
// val memoryUnit = new Cp0MemoryUnit()
|
||||
// val tlb = Vec(
|
||||
// 2,
|
||||
// new Bundle {
|
||||
// val vpn2 = Input(UInt(VPN2_WID.W))
|
||||
|
||||
// val found = Output(Bool())
|
||||
// val info = Output(new TlbEntry())
|
||||
// }
|
||||
// )
|
||||
// })
|
||||
// // 优先使用inst0的信息
|
||||
// val ex_sel = io.memoryUnit.in.inst(0).ex.flush_req || !io.memoryUnit.in.inst(1).ex.flush_req
|
||||
// val pc = Mux(ex_sel, io.memoryUnit.in.inst(0).pc, io.memoryUnit.in.inst(1).pc)
|
||||
// val ex = Mux(ex_sel, io.memoryUnit.in.inst(0).ex, io.memoryUnit.in.inst(1).ex)
|
||||
// val mtc0_wen = io.executeUnit.in.inst_info(0).op === EXE_MTC0
|
||||
// val mtc0_wdata = io.executeUnit.in.mtc0_wdata
|
||||
// val mtc0_addr = io.executeUnit.in.inst_info(0).cp0_addr
|
||||
// val exe_op = io.executeUnit.in.inst_info(0).op
|
||||
// val exe_stall = io.ctrl.exe_stall
|
||||
// val mem_stall = io.ctrl.mem_stall
|
||||
|
||||
// val tlb_l2 = Module(new TlbL2()).io
|
||||
|
||||
// tlb_l2.in.tlb1_vpn2 := io.tlb(0).vpn2
|
||||
// tlb_l2.in.tlb2_vpn2 := io.tlb(1).vpn2
|
||||
// io.tlb(0).found := tlb_l2.out.tlb1_found
|
||||
// io.tlb(1).found := tlb_l2.out.tlb2_found
|
||||
// io.tlb(0).info := tlb_l2.out.tlb1_entry
|
||||
// io.tlb(1).info := tlb_l2.out.tlb2_entry
|
||||
|
||||
// // ---------------cp0-defines-----------------
|
||||
|
||||
// // index register (0,0)
|
||||
// val cp0_index = RegInit(0.U.asTypeOf(new Cp0Index()))
|
||||
|
||||
// // random register (1,0)
|
||||
// val random_init = Wire(new Cp0Random())
|
||||
// random_init := 0.U.asTypeOf(new Cp0Random())
|
||||
// random_init.random := (TLB_NUM - 1).U
|
||||
// val cp0_random = RegInit(random_init)
|
||||
|
||||
// // entrylo0 register (2,0)
|
||||
// val cp0_entrylo0 = RegInit(0.U.asTypeOf(new Cp0EntryLo()))
|
||||
|
||||
// // entrylo1 register (3,0)
|
||||
// val cp0_entrylo1 = RegInit(0.U.asTypeOf(new Cp0EntryLo()))
|
||||
|
||||
// // context register (4,0)
|
||||
// val cp0_context = RegInit(0.U.asTypeOf(new Cp0Context()))
|
||||
|
||||
// // page mask register (5,0)
|
||||
// val cp0_pagemask = 0.U
|
||||
|
||||
// // wired register (6,0)
|
||||
// val cp0_wired = RegInit(0.U.asTypeOf(new Cp0Wired()))
|
||||
|
||||
// // badvaddr register (8,0)
|
||||
// val cp0_badvaddr = RegInit(0.U.asTypeOf(new Cp0BadVAddr()))
|
||||
|
||||
// // count register (9,0)
|
||||
// val count_init = Wire(new Cp0Count())
|
||||
// count_init := 0.U.asTypeOf(new Cp0Count())
|
||||
// count_init.count := 1.U
|
||||
// val cp0_count = RegInit(count_init)
|
||||
|
||||
// // entryhi register (10,0)
|
||||
// val cp0_entryhi = RegInit(0.U.asTypeOf(new Cp0EntryHi()))
|
||||
|
||||
// // compare register (11,0)
|
||||
// val cp0_compare = RegInit(0.U.asTypeOf(new Cp0Compare()))
|
||||
|
||||
// // status register (12,0)
|
||||
// val status_init = Wire(new Cp0Status())
|
||||
// status_init := 0.U.asTypeOf(new Cp0Status())
|
||||
// status_init.bev := true.B
|
||||
// val cp0_status = RegInit(status_init)
|
||||
|
||||
// // cause register (13,0)
|
||||
// val cp0_cause = RegInit(0.U.asTypeOf(new Cp0Cause()))
|
||||
|
||||
// // epc register (14,0)
|
||||
// val cp0_epc = RegInit(0.U.asTypeOf(new Cp0Epc()))
|
||||
|
||||
// // prid register (15,0)
|
||||
// val prid = "h_0001_8003".U
|
||||
|
||||
// // ebase register (15,1)
|
||||
// val ebase_init = Wire(new Cp0Ebase())
|
||||
// ebase_init := 0.U.asTypeOf(new Cp0Ebase())
|
||||
// ebase_init.fill := true.B
|
||||
// val cp0_ebase = RegInit(ebase_init)
|
||||
|
||||
// // config register (16,0)
|
||||
// val cp0_config = Wire(new Cp0Config())
|
||||
// cp0_config := 0.U.asTypeOf(new Cp0Config())
|
||||
// cp0_config.k0 := 3.U
|
||||
// cp0_config.mt := 1.U
|
||||
// cp0_config.m := true.B
|
||||
|
||||
// // config1 register (16,1)
|
||||
// val cp0_config1 = Wire(new Cp0Config1())
|
||||
// cp0_config1 := 0.U.asTypeOf(new Cp0Config1())
|
||||
// cp0_config1.il := 5.U
|
||||
// cp0_config1.ia := 1.U
|
||||
// cp0_config1.dl := 5.U
|
||||
// cp0_config1.da := 1.U
|
||||
// cp0_config1.ms := (TLB_NUM - 1).U
|
||||
|
||||
// // taglo register (28,0)
|
||||
// val cp0_taglo = RegInit(0.U(DATA_WID.W))
|
||||
|
||||
// // taghi register (29,0)
|
||||
// val cp0_taghi = RegInit(0.U(DATA_WID.W))
|
||||
|
||||
// // error epc register (30,0)
|
||||
// val cp0_error_epc = RegInit(0.U.asTypeOf(new Cp0Epc()))
|
||||
|
||||
// tlb_l2.in.write.en := !exe_stall && (exe_op === EXE_TLBWI || exe_op === EXE_TLBWR)
|
||||
// tlb_l2.in.write.index := Mux(exe_op === EXE_TLBWI, cp0_index.index, cp0_random.random)
|
||||
// tlb_l2.in.write.entry.asid := cp0_entryhi.asid
|
||||
// tlb_l2.in.write.entry.vpn2 := cp0_entryhi.vpn2
|
||||
// tlb_l2.in.write.entry.g := cp0_entrylo0.g || cp0_entrylo1.g
|
||||
// tlb_l2.in.write.entry.pfn(0) := cp0_entrylo0.pfn
|
||||
// tlb_l2.in.write.entry.pfn(1) := cp0_entrylo1.pfn
|
||||
// tlb_l2.in.write.entry.c(0) := cp0_entrylo0.c
|
||||
// tlb_l2.in.write.entry.c(1) := cp0_entrylo1.c
|
||||
// tlb_l2.in.write.entry.d(0) := cp0_entrylo0.d
|
||||
// tlb_l2.in.write.entry.d(1) := cp0_entrylo1.d
|
||||
// tlb_l2.in.write.entry.v(0) := cp0_entrylo0.v
|
||||
// tlb_l2.in.write.entry.v(1) := cp0_entrylo1.v
|
||||
// tlb_l2.in.entry_hi.asid := cp0_entryhi.asid
|
||||
// tlb_l2.in.entry_hi.vpn2 := cp0_entryhi.vpn2
|
||||
// tlb_l2.in.read.index := cp0_index.index
|
||||
|
||||
// // index register (0,0)
|
||||
// when(!exe_stall) {
|
||||
// when(mtc0_wen && mtc0_addr === CP0_INDEX_ADDR) {
|
||||
// cp0_index.index := mtc0_wdata(log2Ceil(TLB_NUM) - 1, 0)
|
||||
// }.elsewhen(exe_op === EXE_TLBP) {
|
||||
// cp0_index.index := Mux(tlb_l2.out.tlb_found, tlb_l2.out.tlb_match_index, cp0_index.index)
|
||||
// cp0_index.p := !tlb_l2.out.tlb_found
|
||||
// }
|
||||
// }
|
||||
|
||||
// // random register (1,0)
|
||||
// cp0_random.random := Mux(cp0_random.random === cp0_wired.wired, (TLB_NUM - 1).U, (cp0_random.random - 1.U))
|
||||
|
||||
// // entrylo0 register (2,0)
|
||||
// when(!exe_stall) {
|
||||
// when(mtc0_wen && mtc0_addr === CP0_ENTRYLO0_ADDR) {
|
||||
// val wdata = mtc0_wdata.asTypeOf(new Cp0EntryLo())
|
||||
// cp0_entrylo0.pfn := wdata.pfn
|
||||
// cp0_entrylo0.c := wdata.c
|
||||
// cp0_entrylo0.d := wdata.d
|
||||
// cp0_entrylo0.v := wdata.v
|
||||
// cp0_entrylo0.g := wdata.g
|
||||
// }.elsewhen(exe_op === EXE_TLBR) {
|
||||
// cp0_entrylo0.pfn := tlb_l2.out.read.entry.pfn(0)
|
||||
// cp0_entrylo0.g := tlb_l2.out.read.entry.g
|
||||
// cp0_entrylo0.c := Cat(1.U((C_WID - 1).W), tlb_l2.out.read.entry.c(0))
|
||||
// cp0_entrylo0.d := tlb_l2.out.read.entry.d(0)
|
||||
// cp0_entrylo0.v := tlb_l2.out.read.entry.v(0)
|
||||
// }
|
||||
// }
|
||||
|
||||
// // entrylo1 register (3,0)
|
||||
// when(!exe_stall) {
|
||||
// when(mtc0_wen && mtc0_addr === CP0_ENTRYLO1_ADDR) {
|
||||
// val wdata = mtc0_wdata.asTypeOf(new Cp0EntryLo())
|
||||
// cp0_entrylo1.pfn := wdata.pfn
|
||||
// cp0_entrylo1.c := wdata.c
|
||||
// cp0_entrylo1.d := wdata.d
|
||||
// cp0_entrylo1.v := wdata.v
|
||||
// cp0_entrylo1.g := wdata.g
|
||||
// }.elsewhen(exe_op === EXE_TLBR) {
|
||||
// cp0_entrylo1.pfn := tlb_l2.out.read.entry.pfn(1)
|
||||
// cp0_entrylo1.g := tlb_l2.out.read.entry.g
|
||||
// cp0_entrylo1.c := Cat(1.U((C_WID - 1).W), tlb_l2.out.read.entry.c(1))
|
||||
// cp0_entrylo1.d := tlb_l2.out.read.entry.d(1)
|
||||
// cp0_entrylo1.v := tlb_l2.out.read.entry.v(1)
|
||||
// }
|
||||
// }
|
||||
|
||||
// // context register (4,0)
|
||||
// when(!mem_stall && ex.flush_req) {
|
||||
// when(VecInit(EX_TLBL, EX_TLBS, EX_MOD).contains(ex.excode)) {
|
||||
// cp0_context.badvpn2 := ex.badvaddr(31, 13)
|
||||
// }
|
||||
// }.elsewhen(!exe_stall) {
|
||||
// when(mtc0_wen && mtc0_addr === CP0_CONTEXT_ADDR) {
|
||||
// cp0_context.ptebase := mtc0_wdata.asTypeOf(new Cp0Context()).ptebase
|
||||
// }
|
||||
// }
|
||||
|
||||
// // wired register (6,0)
|
||||
// when(!exe_stall) {
|
||||
// when(mtc0_wen && mtc0_addr === CP0_WIRED_ADDR) {
|
||||
// cp0_wired.wired := mtc0_wdata.asTypeOf(new Cp0Wired()).wired
|
||||
// cp0_random.random := (TLB_NUM - 1).U
|
||||
// }
|
||||
// }
|
||||
|
||||
// // badvaddr register (8,0)
|
||||
// when(!mem_stall && ex.flush_req) {
|
||||
// when(VecInit(EX_ADEL, EX_TLBL, EX_ADES, EX_TLBS, EX_MOD).contains(ex.excode)) {
|
||||
// cp0_badvaddr.badvaddr := ex.badvaddr
|
||||
// }
|
||||
// }
|
||||
|
||||
// // count register (9,0)
|
||||
// val tick = RegInit(false.B)
|
||||
// tick := !tick
|
||||
// when(tick) {
|
||||
// cp0_count.count := cp0_count.count + 1.U
|
||||
// }
|
||||
// when(!exe_stall) {
|
||||
// when(mtc0_wen && mtc0_addr === CP0_COUNT_ADDR) {
|
||||
// cp0_count.count := mtc0_wdata.asTypeOf(new Cp0Count()).count
|
||||
// }
|
||||
// }
|
||||
|
||||
// // entryhi register (10,0)
|
||||
// when(!mem_stall && ex.flush_req) {
|
||||
// when(VecInit(EX_TLBL, EX_TLBS, EX_MOD).contains(ex.excode)) {
|
||||
// cp0_entryhi.vpn2 := ex.badvaddr(31, 13)
|
||||
// }
|
||||
// }.elsewhen(!exe_stall) {
|
||||
// when(mtc0_wen && mtc0_addr === CP0_ENTRYHI_ADDR) {
|
||||
// val wdata = mtc0_wdata.asTypeOf(new Cp0EntryHi())
|
||||
// cp0_entryhi.asid := wdata.asid
|
||||
// cp0_entryhi.vpn2 := wdata.vpn2
|
||||
// }
|
||||
// }
|
||||
|
||||
// // compare register (11,0)
|
||||
// when(!exe_stall) {
|
||||
// when(mtc0_wen && mtc0_addr === CP0_COMPARE_ADDR) {
|
||||
// cp0_compare.compare := mtc0_wdata.asTypeOf(new Cp0Compare()).compare
|
||||
// }
|
||||
// }
|
||||
|
||||
// // status register (12,0)
|
||||
// when(!mem_stall && ex.eret) {
|
||||
// when(cp0_status.erl) {
|
||||
// cp0_status.erl := false.B
|
||||
// }.otherwise {
|
||||
// cp0_status.exl := false.B
|
||||
// }
|
||||
// }.elsewhen(!mem_stall && ex.flush_req) {
|
||||
// cp0_status.exl := true.B
|
||||
// }.elsewhen(!exe_stall) {
|
||||
// when(mtc0_wen && mtc0_addr === CP0_STATUS_ADDR) {
|
||||
// val wdata = mtc0_wdata.asTypeOf(new Cp0Status())
|
||||
// cp0_status.cu0 := wdata.cu0
|
||||
// cp0_status.ie := wdata.ie
|
||||
// cp0_status.exl := wdata.exl
|
||||
// cp0_status.erl := wdata.erl
|
||||
// cp0_status.um := wdata.um
|
||||
// cp0_status.im := wdata.im
|
||||
// cp0_status.bev := wdata.bev
|
||||
// }
|
||||
// }
|
||||
|
||||
// // cause register (13,0)
|
||||
// cp0_cause.ip := Cat(
|
||||
// cp0_cause.ip(7) || cp0_compare.compare === cp0_count.count || io.ext_int(5), // TODO:此处的ext_int可能不对
|
||||
// io.ext_int(4, 0),
|
||||
// cp0_cause.ip(1, 0)
|
||||
// )
|
||||
// when(!mem_stall && ex.flush_req && !ex.eret) {
|
||||
// when(!cp0_status.exl) {
|
||||
// cp0_cause.bd := ex.bd
|
||||
// }
|
||||
// cp0_cause.excode := MuxLookup(ex.excode, cp0_cause.excode)(
|
||||
// Seq(
|
||||
// EX_NO -> EXC_NO,
|
||||
// EX_INT -> EXC_INT,
|
||||
// EX_MOD -> EXC_MOD,
|
||||
// EX_TLBL -> EXC_TLBL,
|
||||
// EX_TLBS -> EXC_TLBS,
|
||||
// EX_ADEL -> EXC_ADEL,
|
||||
// EX_ADES -> EXC_ADES,
|
||||
// EX_SYS -> EXC_SYS,
|
||||
// EX_BP -> EXC_BP,
|
||||
// EX_RI -> EXC_RI,
|
||||
// EX_CPU -> EXC_CPU,
|
||||
// EX_OV -> EXC_OV
|
||||
// )
|
||||
// )
|
||||
// }.elsewhen(!exe_stall) {
|
||||
// when(mtc0_wen) {
|
||||
// when(mtc0_addr === CP0_COMPARE_ADDR) {
|
||||
// cp0_cause.ip := Cat(false.B, cp0_cause.ip(6, 0))
|
||||
// }.elsewhen(mtc0_addr === CP0_CAUSE_ADDR) {
|
||||
// val wdata = mtc0_wdata.asTypeOf(new Cp0Cause())
|
||||
// cp0_cause.ip := Cat(
|
||||
// cp0_cause.ip(7, 2),
|
||||
// wdata.ip(1, 0)
|
||||
// )
|
||||
// cp0_cause.iv := wdata.iv
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // epc register (14,0)
|
||||
// when(!mem_stall && ex.flush_req) {
|
||||
// when(!cp0_status.exl) {
|
||||
// cp0_epc.epc := Mux(ex.bd, pc - 4.U, pc)
|
||||
// }
|
||||
// }.elsewhen(!exe_stall) {
|
||||
// when(mtc0_wen && mtc0_addr === CP0_EPC_ADDR) {
|
||||
// cp0_epc.epc := mtc0_wdata.asTypeOf(new Cp0Epc()).epc
|
||||
// }
|
||||
// }
|
||||
|
||||
// // ebase register (15,1)
|
||||
// when(!exe_stall) {
|
||||
// when(mtc0_wen && mtc0_addr === CP0_EBASE_ADDR) {
|
||||
// cp0_ebase.ebase := mtc0_wdata.asTypeOf(new Cp0Ebase()).ebase
|
||||
// }
|
||||
// }
|
||||
|
||||
// // taglo register (28,0)
|
||||
// when(!exe_stall) {
|
||||
// when(mtc0_wen && mtc0_addr === CP0_TAGLO_ADDR) {
|
||||
// cp0_taglo := mtc0_wdata
|
||||
// }
|
||||
// }
|
||||
|
||||
// // taghi register (29,0)
|
||||
// when(!exe_stall) {
|
||||
// when(mtc0_wen && mtc0_addr === CP0_TAGHI_ADDR) {
|
||||
// cp0_taghi := mtc0_wdata
|
||||
// }
|
||||
// }
|
||||
|
||||
// // error epc register (30,0)
|
||||
// when(!exe_stall) {
|
||||
// when(mtc0_wen && mtc0_addr === CP0_ERROR_EPC_ADDR) {
|
||||
// cp0_error_epc.epc := mtc0_wdata.asTypeOf(new Cp0Epc()).epc
|
||||
// }
|
||||
// }
|
||||
|
||||
// for (i <- 0 until config.fuNum) {
|
||||
// io.executeUnit.out.cp0_rdata(i) := MuxLookup(io.executeUnit.in.inst_info(i).cp0_addr, 0.U)(
|
||||
// Seq(
|
||||
// CP0_INDEX_ADDR -> cp0_index.asUInt,
|
||||
// CP0_RANDOM_ADDR -> cp0_random.asUInt,
|
||||
// CP0_ENTRYLO0_ADDR -> cp0_entrylo0.asUInt,
|
||||
// CP0_ENTRYLO1_ADDR -> cp0_entrylo1.asUInt,
|
||||
// CP0_CONTEXT_ADDR -> cp0_context.asUInt,
|
||||
// CP0_PAGE_MASK_ADDR -> cp0_pagemask,
|
||||
// CP0_WIRED_ADDR -> cp0_wired.asUInt,
|
||||
// CP0_BADV_ADDR -> cp0_badvaddr.asUInt,
|
||||
// CP0_COUNT_ADDR -> cp0_count.asUInt,
|
||||
// CP0_ENTRYHI_ADDR -> cp0_entryhi.asUInt,
|
||||
// CP0_COMPARE_ADDR -> cp0_compare.asUInt,
|
||||
// CP0_STATUS_ADDR -> cp0_status.asUInt,
|
||||
// CP0_CAUSE_ADDR -> cp0_cause.asUInt,
|
||||
// CP0_EPC_ADDR -> cp0_epc.asUInt,
|
||||
// CP0_PRID_ADDR -> prid,
|
||||
// CP0_EBASE_ADDR -> cp0_ebase.asUInt,
|
||||
// CP0_CONFIG_ADDR -> cp0_config.asUInt,
|
||||
// CP0_CONFIG1_ADDR -> cp0_config1.asUInt,
|
||||
// CP0_TAGLO_ADDR -> cp0_taglo,
|
||||
// CP0_TAGHI_ADDR -> cp0_taghi,
|
||||
// CP0_ERROR_EPC_ADDR -> cp0_error_epc.asUInt
|
||||
// )
|
||||
// )
|
||||
// }
|
||||
// io.decoderUnit.cause_ip := cp0_cause.ip
|
||||
// io.decoderUnit.status_im := cp0_status.im
|
||||
// io.decoderUnit.kernel_mode := (cp0_status.exl && !(ex.eret && cp0_status.erl)) ||
|
||||
// (cp0_status.erl && !ex.eret) ||
|
||||
// !cp0_status.um ||
|
||||
// (ex.flush_req && !ex.eret)
|
||||
// io.decoderUnit.access_allowed := io.decoderUnit.kernel_mode || cp0_status.cu0
|
||||
// io.decoderUnit.intterupt_allowed := cp0_status.ie && !cp0_status.exl && !cp0_status.erl
|
||||
|
||||
// io.executeUnit.out.debug.cp0_cause := cp0_cause.asUInt
|
||||
// io.executeUnit.out.debug.cp0_count := cp0_count.asUInt
|
||||
// io.executeUnit.out.debug.cp0_random := cp0_random.asUInt
|
||||
|
||||
// val trap_base = Mux(
|
||||
// cp0_status.bev,
|
||||
// "hbfc00200".U(PC_WID.W),
|
||||
// cp0_ebase.asUInt
|
||||
// )
|
||||
// io.memoryUnit.out.flush := false.B
|
||||
// io.memoryUnit.out.flush_pc := 0.U
|
||||
// when(ex.eret) {
|
||||
// io.memoryUnit.out.flush := true.B && !io.ctrl.mem_stall
|
||||
// io.memoryUnit.out.flush_pc := Mux(cp0_status.erl, cp0_error_epc.epc, cp0_epc.epc)
|
||||
// }.elsewhen(ex.flush_req) {
|
||||
// io.memoryUnit.out.flush := true.B && !io.ctrl.mem_stall
|
||||
// io.memoryUnit.out.flush_pc := Mux(
|
||||
// cp0_status.exl,
|
||||
// trap_base + "h180".U,
|
||||
// trap_base + Mux(
|
||||
// ex.excode === EX_INT && cp0_cause.iv && !cp0_status.bev,
|
||||
// "h200".U,
|
||||
// Mux(ex.tlb_refill && ex.excode =/= EX_INT, 0.U, "h180".U)
|
||||
// )
|
||||
// )
|
||||
// }
|
||||
// }
|
|
@ -0,0 +1,368 @@
|
|||
package cpu.pipeline.execute
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import cpu.defines._
|
||||
import cpu.defines.Const._
|
||||
import cpu.pipeline.memory.CsrInfo
|
||||
import cpu.CpuConfig
|
||||
import cpu.pipeline.decoder.CsrDecoderUnit
|
||||
|
||||
class CsrMemoryUnit(implicit val config: CpuConfig) extends Bundle {
|
||||
val in = Input(new Bundle {
|
||||
val inst = Vec(
|
||||
config.fuNum,
|
||||
new Bundle {
|
||||
val pc = UInt(PC_WID.W)
|
||||
val ex = new ExceptionInfo()
|
||||
}
|
||||
)
|
||||
})
|
||||
val out = Output(new Bundle {
|
||||
val flush = Bool()
|
||||
val flush_pc = UInt(PC_WID.W)
|
||||
})
|
||||
}
|
||||
|
||||
class CsrExecuteUnit(implicit val config: CpuConfig) extends Bundle {
|
||||
val in = Input(new Bundle {
|
||||
val inst_info = Vec(config.fuNum, new InstInfo())
|
||||
val mtc0_wdata = UInt(DATA_WID.W)
|
||||
})
|
||||
val out = Output(new Bundle {
|
||||
val csr_rdata = Vec(config.fuNum, UInt(DATA_WID.W))
|
||||
val debug = Output(new CsrInfo())
|
||||
})
|
||||
}
|
||||
|
||||
class Csr(implicit val config: CpuConfig) extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val ext_int = Input(UInt(EXT_INT_WID.W))
|
||||
val ctrl = Input(new Bundle {
|
||||
val exe_stall = Bool()
|
||||
val mem_stall = Bool()
|
||||
})
|
||||
val decoderUnit = Output(new CsrDecoderUnit())
|
||||
val executeUnit = new CsrExecuteUnit()
|
||||
val memoryUnit = new CsrMemoryUnit()
|
||||
})
|
||||
// 优先使用inst0的信息
|
||||
val ex_sel = io.memoryUnit.in.inst(0).ex.flush_req || !io.memoryUnit.in.inst(1).ex.flush_req
|
||||
val pc = Mux(ex_sel, io.memoryUnit.in.inst(0).pc, io.memoryUnit.in.inst(1).pc)
|
||||
val ex = Mux(ex_sel, io.memoryUnit.in.inst(0).ex, io.memoryUnit.in.inst(1).ex)
|
||||
val mtc0_wen = io.executeUnit.in.inst_info(0).op === EXE_MTC0
|
||||
val mtc0_wdata = io.executeUnit.in.mtc0_wdata
|
||||
val mtc0_addr = io.executeUnit.in.inst_info(0).csr_addr
|
||||
val exe_op = io.executeUnit.in.inst_info(0).op
|
||||
val exe_stall = io.ctrl.exe_stall
|
||||
val mem_stall = io.ctrl.mem_stall
|
||||
|
||||
// ---------------csr-defines-----------------
|
||||
|
||||
// index register (0,0)
|
||||
val csr_index = RegInit(0.U.asTypeOf(new CsrIndex()))
|
||||
|
||||
// random register (1,0)
|
||||
val random_init = Wire(new CsrRandom())
|
||||
random_init := 0.U.asTypeOf(new CsrRandom())
|
||||
random_init.random := (TLB_NUM - 1).U
|
||||
val csr_random = RegInit(random_init)
|
||||
|
||||
// entrylo0 register (2,0)
|
||||
val csr_entrylo0 = RegInit(0.U.asTypeOf(new CsrEntryLo()))
|
||||
|
||||
// entrylo1 register (3,0)
|
||||
val csr_entrylo1 = RegInit(0.U.asTypeOf(new CsrEntryLo()))
|
||||
|
||||
// context register (4,0)
|
||||
val csr_context = RegInit(0.U.asTypeOf(new CsrContext()))
|
||||
|
||||
// page mask register (5,0)
|
||||
val csr_pagemask = 0.U
|
||||
|
||||
// wired register (6,0)
|
||||
val csr_wired = RegInit(0.U.asTypeOf(new CsrWired()))
|
||||
|
||||
// badvaddr register (8,0)
|
||||
val csr_badvaddr = RegInit(0.U.asTypeOf(new CsrBadVAddr()))
|
||||
|
||||
// count register (9,0)
|
||||
val count_init = Wire(new CsrCount())
|
||||
count_init := 0.U.asTypeOf(new CsrCount())
|
||||
count_init.count := 1.U
|
||||
val csr_count = RegInit(count_init)
|
||||
|
||||
// entryhi register (10,0)
|
||||
val csr_entryhi = RegInit(0.U.asTypeOf(new CsrEntryHi()))
|
||||
|
||||
// compare register (11,0)
|
||||
val csr_compare = RegInit(0.U.asTypeOf(new CsrCompare()))
|
||||
|
||||
// status register (12,0)
|
||||
val status_init = Wire(new CsrStatus())
|
||||
status_init := 0.U.asTypeOf(new CsrStatus())
|
||||
status_init.bev := true.B
|
||||
val csr_status = RegInit(status_init)
|
||||
|
||||
// cause register (13,0)
|
||||
val csr_cause = RegInit(0.U.asTypeOf(new CsrCause()))
|
||||
|
||||
// epc register (14,0)
|
||||
val csr_epc = RegInit(0.U.asTypeOf(new CsrEpc()))
|
||||
|
||||
// prid register (15,0)
|
||||
val prid = "h_0001_8003".U
|
||||
|
||||
// ebase register (15,1)
|
||||
val ebase_init = Wire(new CsrEbase())
|
||||
ebase_init := 0.U.asTypeOf(new CsrEbase())
|
||||
ebase_init.fill := true.B
|
||||
val csr_ebase = RegInit(ebase_init)
|
||||
|
||||
// config register (16,0)
|
||||
val csr_config = Wire(new CsrConfig())
|
||||
csr_config := 0.U.asTypeOf(new CsrConfig())
|
||||
csr_config.k0 := 3.U
|
||||
csr_config.mt := 1.U
|
||||
csr_config.m := true.B
|
||||
|
||||
// config1 register (16,1)
|
||||
val csr_config1 = Wire(new CsrConfig1())
|
||||
csr_config1 := 0.U.asTypeOf(new CsrConfig1())
|
||||
csr_config1.il := 5.U
|
||||
csr_config1.ia := 1.U
|
||||
csr_config1.dl := 5.U
|
||||
csr_config1.da := 1.U
|
||||
csr_config1.ms := (TLB_NUM - 1).U
|
||||
|
||||
// taglo register (28,0)
|
||||
val csr_taglo = RegInit(0.U(DATA_WID.W))
|
||||
|
||||
// taghi register (29,0)
|
||||
val csr_taghi = RegInit(0.U(DATA_WID.W))
|
||||
|
||||
// error epc register (30,0)
|
||||
val csr_error_epc = RegInit(0.U.asTypeOf(new CsrEpc()))
|
||||
|
||||
// random register (1,0)
|
||||
csr_random.random := Mux(csr_random.random === csr_wired.wired, (TLB_NUM - 1).U, (csr_random.random - 1.U))
|
||||
|
||||
// context register (4,0)
|
||||
when(!mem_stall && ex.flush_req) {
|
||||
when(VecInit(EX_TLBL, EX_TLBS, EX_MOD).contains(ex.excode)) {
|
||||
csr_context.badvpn2 := ex.badvaddr(31, 13)
|
||||
}
|
||||
}.elsewhen(!exe_stall) {
|
||||
when(mtc0_wen && mtc0_addr === CSR_CONTEXT_ADDR) {
|
||||
csr_context.ptebase := mtc0_wdata.asTypeOf(new CsrContext()).ptebase
|
||||
}
|
||||
}
|
||||
|
||||
// wired register (6,0)
|
||||
when(!exe_stall) {
|
||||
when(mtc0_wen && mtc0_addr === CSR_WIRED_ADDR) {
|
||||
csr_wired.wired := mtc0_wdata.asTypeOf(new CsrWired()).wired
|
||||
csr_random.random := (TLB_NUM - 1).U
|
||||
}
|
||||
}
|
||||
|
||||
// badvaddr register (8,0)
|
||||
when(!mem_stall && ex.flush_req) {
|
||||
when(VecInit(EX_ADEL, EX_TLBL, EX_ADES, EX_TLBS, EX_MOD).contains(ex.excode)) {
|
||||
csr_badvaddr.badvaddr := ex.badvaddr
|
||||
}
|
||||
}
|
||||
|
||||
// count register (9,0)
|
||||
val tick = RegInit(false.B)
|
||||
tick := !tick
|
||||
when(tick) {
|
||||
csr_count.count := csr_count.count + 1.U
|
||||
}
|
||||
when(!exe_stall) {
|
||||
when(mtc0_wen && mtc0_addr === CSR_COUNT_ADDR) {
|
||||
csr_count.count := mtc0_wdata.asTypeOf(new CsrCount()).count
|
||||
}
|
||||
}
|
||||
|
||||
// entryhi register (10,0)
|
||||
when(!mem_stall && ex.flush_req) {
|
||||
when(VecInit(EX_TLBL, EX_TLBS, EX_MOD).contains(ex.excode)) {
|
||||
csr_entryhi.vpn2 := ex.badvaddr(31, 13)
|
||||
}
|
||||
}.elsewhen(!exe_stall) {
|
||||
when(mtc0_wen && mtc0_addr === CSR_ENTRYHI_ADDR) {
|
||||
val wdata = mtc0_wdata.asTypeOf(new CsrEntryHi())
|
||||
csr_entryhi.asid := wdata.asid
|
||||
csr_entryhi.vpn2 := wdata.vpn2
|
||||
}
|
||||
}
|
||||
|
||||
// compare register (11,0)
|
||||
when(!exe_stall) {
|
||||
when(mtc0_wen && mtc0_addr === CSR_COMPARE_ADDR) {
|
||||
csr_compare.compare := mtc0_wdata.asTypeOf(new CsrCompare()).compare
|
||||
}
|
||||
}
|
||||
|
||||
// status register (12,0)
|
||||
when(!mem_stall && ex.eret) {
|
||||
when(csr_status.erl) {
|
||||
csr_status.erl := false.B
|
||||
}.otherwise {
|
||||
csr_status.exl := false.B
|
||||
}
|
||||
}.elsewhen(!mem_stall && ex.flush_req) {
|
||||
csr_status.exl := true.B
|
||||
}.elsewhen(!exe_stall) {
|
||||
when(mtc0_wen && mtc0_addr === CSR_STATUS_ADDR) {
|
||||
val wdata = mtc0_wdata.asTypeOf(new CsrStatus())
|
||||
csr_status.cu0 := wdata.cu0
|
||||
csr_status.ie := wdata.ie
|
||||
csr_status.exl := wdata.exl
|
||||
csr_status.erl := wdata.erl
|
||||
csr_status.um := wdata.um
|
||||
csr_status.im := wdata.im
|
||||
csr_status.bev := wdata.bev
|
||||
}
|
||||
}
|
||||
|
||||
// cause register (13,0)
|
||||
csr_cause.ip := Cat(
|
||||
csr_cause.ip(7) || csr_compare.compare === csr_count.count || io.ext_int(5), // TODO:此处的ext_int可能不对
|
||||
io.ext_int(4, 0),
|
||||
csr_cause.ip(1, 0)
|
||||
)
|
||||
when(!mem_stall && ex.flush_req && !ex.eret) {
|
||||
when(!csr_status.exl) {
|
||||
csr_cause.bd := ex.bd
|
||||
}
|
||||
csr_cause.excode := MuxLookup(ex.excode, csr_cause.excode)(
|
||||
Seq(
|
||||
EX_NO -> EXC_NO,
|
||||
EX_INT -> EXC_INT,
|
||||
EX_MOD -> EXC_MOD,
|
||||
EX_TLBL -> EXC_TLBL,
|
||||
EX_TLBS -> EXC_TLBS,
|
||||
EX_ADEL -> EXC_ADEL,
|
||||
EX_ADES -> EXC_ADES,
|
||||
EX_SYS -> EXC_SYS,
|
||||
EX_BP -> EXC_BP,
|
||||
EX_RI -> EXC_RI,
|
||||
EX_CPU -> EXC_CPU,
|
||||
EX_OV -> EXC_OV
|
||||
)
|
||||
)
|
||||
}.elsewhen(!exe_stall) {
|
||||
when(mtc0_wen) {
|
||||
when(mtc0_addr === CSR_COMPARE_ADDR) {
|
||||
csr_cause.ip := Cat(false.B, csr_cause.ip(6, 0))
|
||||
}.elsewhen(mtc0_addr === CSR_CAUSE_ADDR) {
|
||||
val wdata = mtc0_wdata.asTypeOf(new CsrCause())
|
||||
csr_cause.ip := Cat(
|
||||
csr_cause.ip(7, 2),
|
||||
wdata.ip(1, 0)
|
||||
)
|
||||
csr_cause.iv := wdata.iv
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// epc register (14,0)
|
||||
when(!mem_stall && ex.flush_req) {
|
||||
when(!csr_status.exl) {
|
||||
csr_epc.epc := Mux(ex.bd, pc - 4.U, pc)
|
||||
}
|
||||
}.elsewhen(!exe_stall) {
|
||||
when(mtc0_wen && mtc0_addr === CSR_EPC_ADDR) {
|
||||
csr_epc.epc := mtc0_wdata.asTypeOf(new CsrEpc()).epc
|
||||
}
|
||||
}
|
||||
|
||||
// ebase register (15,1)
|
||||
when(!exe_stall) {
|
||||
when(mtc0_wen && mtc0_addr === CSR_EBASE_ADDR) {
|
||||
csr_ebase.ebase := mtc0_wdata.asTypeOf(new CsrEbase()).ebase
|
||||
}
|
||||
}
|
||||
|
||||
// taglo register (28,0)
|
||||
when(!exe_stall) {
|
||||
when(mtc0_wen && mtc0_addr === CSR_TAGLO_ADDR) {
|
||||
csr_taglo := mtc0_wdata
|
||||
}
|
||||
}
|
||||
|
||||
// taghi register (29,0)
|
||||
when(!exe_stall) {
|
||||
when(mtc0_wen && mtc0_addr === CSR_TAGHI_ADDR) {
|
||||
csr_taghi := mtc0_wdata
|
||||
}
|
||||
}
|
||||
|
||||
// error epc register (30,0)
|
||||
when(!exe_stall) {
|
||||
when(mtc0_wen && mtc0_addr === CSR_ERROR_EPC_ADDR) {
|
||||
csr_error_epc.epc := mtc0_wdata.asTypeOf(new CsrEpc()).epc
|
||||
}
|
||||
}
|
||||
|
||||
for (i <- 0 until config.fuNum) {
|
||||
io.executeUnit.out.csr_rdata(i) := MuxLookup(io.executeUnit.in.inst_info(i).csr_addr, 0.U)(
|
||||
Seq(
|
||||
CSR_INDEX_ADDR -> csr_index.asUInt,
|
||||
CSR_RANDOM_ADDR -> csr_random.asUInt,
|
||||
CSR_ENTRYLO0_ADDR -> csr_entrylo0.asUInt,
|
||||
CSR_ENTRYLO1_ADDR -> csr_entrylo1.asUInt,
|
||||
CSR_CONTEXT_ADDR -> csr_context.asUInt,
|
||||
CSR_PAGE_MASK_ADDR -> csr_pagemask,
|
||||
CSR_WIRED_ADDR -> csr_wired.asUInt,
|
||||
CSR_BADV_ADDR -> csr_badvaddr.asUInt,
|
||||
CSR_COUNT_ADDR -> csr_count.asUInt,
|
||||
CSR_ENTRYHI_ADDR -> csr_entryhi.asUInt,
|
||||
CSR_COMPARE_ADDR -> csr_compare.asUInt,
|
||||
CSR_STATUS_ADDR -> csr_status.asUInt,
|
||||
CSR_CAUSE_ADDR -> csr_cause.asUInt,
|
||||
CSR_EPC_ADDR -> csr_epc.asUInt,
|
||||
CSR_PRID_ADDR -> prid,
|
||||
CSR_EBASE_ADDR -> csr_ebase.asUInt,
|
||||
CSR_CONFIG_ADDR -> csr_config.asUInt,
|
||||
CSR_CONFIG1_ADDR -> csr_config1.asUInt,
|
||||
CSR_TAGLO_ADDR -> csr_taglo,
|
||||
CSR_TAGHI_ADDR -> csr_taghi,
|
||||
CSR_ERROR_EPC_ADDR -> csr_error_epc.asUInt
|
||||
)
|
||||
)
|
||||
}
|
||||
io.decoderUnit.cause_ip := csr_cause.ip
|
||||
io.decoderUnit.status_im := csr_status.im
|
||||
io.decoderUnit.kernel_mode := (csr_status.exl && !(ex.eret && csr_status.erl)) ||
|
||||
(csr_status.erl && !ex.eret) ||
|
||||
!csr_status.um ||
|
||||
(ex.flush_req && !ex.eret)
|
||||
io.decoderUnit.access_allowed := io.decoderUnit.kernel_mode || csr_status.cu0
|
||||
io.decoderUnit.intterupt_allowed := csr_status.ie && !csr_status.exl && !csr_status.erl
|
||||
|
||||
io.executeUnit.out.debug.csr_cause := csr_cause.asUInt
|
||||
io.executeUnit.out.debug.csr_count := csr_count.asUInt
|
||||
io.executeUnit.out.debug.csr_random := csr_random.asUInt
|
||||
|
||||
val trap_base = Mux(
|
||||
csr_status.bev,
|
||||
"hbfc00200".U(PC_WID.W),
|
||||
csr_ebase.asUInt
|
||||
)
|
||||
io.memoryUnit.out.flush := false.B
|
||||
io.memoryUnit.out.flush_pc := 0.U
|
||||
when(ex.eret) {
|
||||
io.memoryUnit.out.flush := true.B && !io.ctrl.mem_stall
|
||||
io.memoryUnit.out.flush_pc := Mux(csr_status.erl, csr_error_epc.epc, csr_epc.epc)
|
||||
}.elsewhen(ex.flush_req) {
|
||||
io.memoryUnit.out.flush := true.B && !io.ctrl.mem_stall
|
||||
io.memoryUnit.out.flush_pc := Mux(
|
||||
csr_status.exl,
|
||||
trap_base + "h180".U,
|
||||
trap_base + "h200".U
|
||||
)
|
||||
}
|
||||
}
|
|
@ -6,14 +6,14 @@ import cpu.CpuConfig
|
|||
import cpu.defines._
|
||||
import cpu.defines.Const._
|
||||
import cpu.pipeline.decoder.RegWrite
|
||||
import cpu.pipeline.memory.{ExecuteUnitMemoryUnit, Cp0Info}
|
||||
import cpu.pipeline.memory.{ExecuteUnitMemoryUnit, CsrInfo}
|
||||
import cpu.pipeline.fetch.ExecuteUnitBranchPredictor
|
||||
|
||||
class ExecuteUnit(implicit val config: CpuConfig) extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val ctrl = new ExecuteCtrl()
|
||||
val executeStage = Input(new DecoderUnitExecuteUnit())
|
||||
val cp0 = Flipped(new Cp0ExecuteUnit())
|
||||
val csr = Flipped(new CsrExecuteUnit())
|
||||
val bpu = new ExecuteUnitBranchPredictor()
|
||||
val fetchUnit = Output(new Bundle {
|
||||
val branch = Bool()
|
||||
|
@ -46,13 +46,13 @@ class ExecuteUnit(implicit val config: CpuConfig) extends Module {
|
|||
io.ctrl.branch := io.ctrl.allow_to_go &&
|
||||
(io.executeStage.inst0.jb_info.jump_regiser || fu.branch.pred_fail)
|
||||
|
||||
io.cp0.in.mtc0_wdata := io.executeStage.inst0.src_info.src2_data
|
||||
io.cp0.in.inst_info(0) := Mux(
|
||||
io.csr.in.mtc0_wdata := io.executeStage.inst0.src_info.src2_data
|
||||
io.csr.in.inst_info(0) := Mux(
|
||||
!io.executeStage.inst0.ex.flush_req,
|
||||
io.executeStage.inst0.inst_info,
|
||||
0.U.asTypeOf(new InstInfo()),
|
||||
)
|
||||
io.cp0.in.inst_info(1) := io.executeStage.inst1.inst_info
|
||||
io.csr.in.inst_info(1) := io.executeStage.inst1.inst_info
|
||||
|
||||
// input accessMemCtrl
|
||||
accessMemCtrl.inst(0).inst_info := io.executeStage.inst0.inst_info
|
||||
|
@ -79,7 +79,7 @@ class ExecuteUnit(implicit val config: CpuConfig) extends Module {
|
|||
fu.inst(1).inst_info := io.executeStage.inst1.inst_info
|
||||
fu.inst(1).src_info := io.executeStage.inst1.src_info
|
||||
fu.inst(1).ex.in := io.executeStage.inst1.ex
|
||||
fu.cp0_rdata := io.cp0.out.cp0_rdata
|
||||
fu.csr_rdata := io.csr.out.csr_rdata
|
||||
fu.branch.pred_branch := io.executeStage.inst0.jb_info.pred_branch
|
||||
|
||||
io.bpu.pc := io.executeStage.inst0.pc
|
||||
|
@ -121,7 +121,7 @@ class ExecuteUnit(implicit val config: CpuConfig) extends Module {
|
|||
accessMemCtrl.inst(0).ex.out,
|
||||
fu.inst(0).ex.out,
|
||||
)
|
||||
io.memoryStage.inst0.cp0 := io.cp0.out.debug
|
||||
io.memoryStage.inst0.csr := io.csr.out.debug
|
||||
|
||||
io.memoryStage.inst1.pc := io.executeStage.inst1.pc
|
||||
io.memoryStage.inst1.inst_info := io.executeStage.inst1.inst_info
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
// val result = Output(UInt(DATA_WID.W))
|
||||
// },
|
||||
// )
|
||||
// val cp0_rdata = Input(Vec(config.fuNum, UInt(DATA_WID.W)))
|
||||
// val csr_rdata = Input(Vec(config.fuNum, UInt(DATA_WID.W)))
|
||||
// val stall_req = Output(Bool())
|
||||
// val branch = new Bundle {
|
||||
// val pred_branch = Input(Bool())
|
||||
|
@ -58,7 +58,7 @@
|
|||
// alu(i).io.mul.ready := mul.ready
|
||||
// alu(i).io.div.ready := div.ready
|
||||
// alu(i).io.div.result := div.result
|
||||
// alu(i).io.cp0_rdata := io.cp0_rdata(i)
|
||||
// alu(i).io.csr_rdata := io.csr_rdata(i)
|
||||
// alu(i).io.llbit := io.llbit
|
||||
// io.inst(i).ex.out := io.inst(i).ex.in
|
||||
// io.inst(i).ex.out.flush_req := io.inst(i).ex.in.flush_req || alu(i).io.overflow
|
||||
|
|
|
@ -16,7 +16,6 @@ class InstFifo(implicit val config: CpuConfig) extends Module {
|
|||
val io = IO(new Bundle {
|
||||
val do_flush = Input(Bool())
|
||||
val icache_stall = Input(Bool())
|
||||
val jump_branch_inst = Input(Bool()) // 译码阶段的inst0是否为跳转指令
|
||||
|
||||
val ren = Input(Vec(config.decoderNum, Bool()))
|
||||
val read = Output(Vec(config.decoderNum, new BufferUnit()))
|
||||
|
|
|
@ -6,10 +6,10 @@ import cpu.defines._
|
|||
import cpu.defines.Const._
|
||||
import cpu.CpuConfig
|
||||
|
||||
class Cp0Info extends Bundle {
|
||||
val cp0_count = UInt(DATA_WID.W)
|
||||
val cp0_random = UInt(DATA_WID.W)
|
||||
val cp0_cause = UInt(DATA_WID.W)
|
||||
class CsrInfo extends Bundle {
|
||||
val csr_count = UInt(DATA_WID.W)
|
||||
val csr_random = UInt(DATA_WID.W)
|
||||
val csr_cause = UInt(DATA_WID.W)
|
||||
}
|
||||
|
||||
class ExeMemInst1 extends Bundle {
|
||||
|
@ -20,7 +20,7 @@ class ExeMemInst1 extends Bundle {
|
|||
}
|
||||
|
||||
class ExeMemInst0(implicit val config: CpuConfig) extends ExeMemInst1 {
|
||||
val cp0 = new Cp0Info()
|
||||
val csr = new CsrInfo()
|
||||
val mem = new Bundle {
|
||||
val en = Bool()
|
||||
val ren = Bool()
|
||||
|
|
|
@ -6,7 +6,7 @@ import cpu.defines._
|
|||
import cpu.defines.Const._
|
||||
import cpu.CpuConfig
|
||||
import cpu.pipeline.decoder.RegWrite
|
||||
import cpu.pipeline.execute.Cp0MemoryUnit
|
||||
import cpu.pipeline.execute.CsrMemoryUnit
|
||||
import cpu.pipeline.writeback.MemoryUnitWriteBackUnit
|
||||
|
||||
class MemoryUnit(implicit val config: CpuConfig) extends Module {
|
||||
|
@ -18,7 +18,7 @@ class MemoryUnit(implicit val config: CpuConfig) extends Module {
|
|||
val flush_pc = UInt(PC_WID.W)
|
||||
})
|
||||
val decoderUnit = Output(Vec(config.fuNum, new RegWrite()))
|
||||
val cp0 = Flipped(new Cp0MemoryUnit())
|
||||
val csr = Flipped(new CsrMemoryUnit())
|
||||
val writeBackStage = Output(new MemoryUnitWriteBackUnit())
|
||||
val dataMemory = new Bundle {
|
||||
val in = Input(new Bundle {
|
||||
|
@ -68,7 +68,7 @@ class MemoryUnit(implicit val config: CpuConfig) extends Module {
|
|||
),
|
||||
)
|
||||
io.writeBackStage.inst0.ex.flush_req := io.memoryStage.inst0.ex.flush_req || io.writeBackStage.inst0.ex.excode =/= EX_NO
|
||||
io.writeBackStage.inst0.cp0 := io.memoryStage.inst0.cp0
|
||||
io.writeBackStage.inst0.csr := io.memoryStage.inst0.csr
|
||||
|
||||
io.writeBackStage.inst1.pc := io.memoryStage.inst1.pc
|
||||
io.writeBackStage.inst1.inst_info := io.memoryStage.inst1.inst_info
|
||||
|
@ -86,17 +86,17 @@ class MemoryUnit(implicit val config: CpuConfig) extends Module {
|
|||
)
|
||||
io.writeBackStage.inst1.ex.flush_req := io.memoryStage.inst1.ex.flush_req || io.writeBackStage.inst1.ex.excode =/= EX_NO
|
||||
|
||||
io.cp0.in.inst(0).pc := io.writeBackStage.inst0.pc
|
||||
io.cp0.in.inst(0).ex := io.writeBackStage.inst0.ex
|
||||
io.cp0.in.inst(1).pc := io.writeBackStage.inst1.pc
|
||||
io.cp0.in.inst(1).ex := io.writeBackStage.inst1.ex
|
||||
io.csr.in.inst(0).pc := io.writeBackStage.inst0.pc
|
||||
io.csr.in.inst(0).ex := io.writeBackStage.inst0.ex
|
||||
io.csr.in.inst(1).pc := io.writeBackStage.inst1.pc
|
||||
io.csr.in.inst(1).ex := io.writeBackStage.inst1.ex
|
||||
|
||||
io.fetchUnit.flush := Mux(
|
||||
io.cp0.out.flush,
|
||||
io.cp0.out.flush,
|
||||
io.csr.out.flush,
|
||||
io.csr.out.flush,
|
||||
io.writeBackStage.inst0.inst_info.op === EXE_MTC0 && io.ctrl.allow_to_go,
|
||||
)
|
||||
io.fetchUnit.flush_pc := Mux(io.cp0.out.flush, io.cp0.out.flush_pc, io.writeBackStage.inst0.pc + 4.U)
|
||||
io.fetchUnit.flush_pc := Mux(io.csr.out.flush, io.csr.out.flush_pc, io.writeBackStage.inst0.pc + 4.U)
|
||||
|
||||
io.ctrl.flush_req := io.fetchUnit.flush
|
||||
io.ctrl.eret := io.writeBackStage.inst0.ex.eret
|
||||
|
|
|
@ -5,7 +5,7 @@ import chisel3.util._
|
|||
import cpu.defines._
|
||||
import cpu.defines.Const._
|
||||
import cpu.CpuConfig
|
||||
import cpu.pipeline.memory.Cp0Info
|
||||
import cpu.pipeline.memory.CsrInfo
|
||||
|
||||
class MemWbInst1 extends Bundle {
|
||||
val pc = UInt(PC_WID.W)
|
||||
|
@ -14,7 +14,7 @@ class MemWbInst1 extends Bundle {
|
|||
val ex = new ExceptionInfo()
|
||||
}
|
||||
class MemWbInst0 extends MemWbInst1 {
|
||||
val cp0 = new Cp0Info()
|
||||
val csr = new CsrInfo()
|
||||
}
|
||||
|
||||
class MemoryUnitWriteBackUnit extends Bundle {
|
||||
|
|
|
@ -69,9 +69,9 @@ class WriteBackUnit(implicit val config: CpuConfig) extends Module {
|
|||
// statistic
|
||||
// ===----------------------------------------------------------------===
|
||||
if (!config.build) {
|
||||
io.statistic.get.cp0_cause := io.writeBackStage.inst0.cp0.cp0_cause
|
||||
io.statistic.get.cp0_count := io.writeBackStage.inst0.cp0.cp0_count
|
||||
io.statistic.get.cp0_random := io.writeBackStage.inst0.cp0.cp0_random
|
||||
io.statistic.get.csr_cause := io.writeBackStage.inst0.csr.csr_cause
|
||||
io.statistic.get.csr_count := io.writeBackStage.inst0.csr.csr_count
|
||||
io.statistic.get.csr_random := io.writeBackStage.inst0.csr.csr_random
|
||||
io.statistic.get.int := io.writeBackStage.inst0.ex.excode === EX_INT
|
||||
io.statistic.get.commit := io.ctrl.allow_to_go
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue