package E203_EXU_ALU_DPATH
import chisel3._
import chisel3.util._
import chisel3.util.experimental._
import chisel3.stage.ChiselGeneratorAnnotation
case class EXCP_PARAM(E203_ADDR_SIZE : Int,E203_PC_SIZE : Int,E203_INSTR_SIZE : Int,E203_XLEN : Int,E203_LIRQ_NUM : Int){
require(E203_ADDR_SIZE >= 16)
require(E203_PC_SIZE >=16)
require(E203_INSTR_SIZE >=32)
require(E203_XLEN >=16)
require(E203_LIRQ_NUM >=1)
}
class E203_EXU_WFI_EXCP_INTF extends Bundle{
val core_wfi = Output(UInt(1.W))
val wfi_halt_ifu_req = Output(UInt(1.W))
val wfi_halt_exu_req = Output(UInt(1.W))
val wfi_halt_ifu_ack = Input(UInt(1.W))
val wfi_halt_exu_ack = Input(UInt(1.W))
}
class E203_EXU_ALU_EXCP_INTF (val p : EXCP_PARAM) extends Bundle{
val alu_excp_i_ready = Output(UInt(1.W))
val alu_excp_i_valid = Input(UInt(1.W))
val alu_excp_i_ld = Input(UInt(1.W))
val alu_excp_i_stamo = Input(UInt(1.W))
val alu_excp_i_misalgn = Input(UInt(1.W))
val alu_excp_i_buserr = Input(UInt(1.W))
val alu_excp_i_ecall = Input(UInt(1.W))
val alu_excp_i_ebreak = Input(UInt(1.W))
val alu_excp_i_wfi = Input(UInt(1.W))
val alu_excp_i_ifu_misalgn = Input(UInt(1.W))
val alu_excp_i_ifu_buserr = Input(UInt(1.W))
val alu_excp_i_ifu_ilegl = Input(UInt(1.W))
val alu_excp_i_badaddr = Input(UInt(p.E203_ADDR_SIZE.W))
val alu_excp_i_pc = Input(UInt(p.E203_PC_SIZE.W))
val alu_excp_i_instr = Input(UInt(p.E203_INSTR_SIZE.W))
val alu_excp_i_pc_vld = Input(UInt(1.W))
}
class E203_EXU_LONGP_EXCP_INTF (val p : EXCP_PARAM) extends Bundle{
val longp_excp_i_ready = Output(UInt(1.W))
val longp_excp_i_valid = Input(UInt(1.W))
val longp_excp_i_ld = Input(UInt(1.W))
val longp_excp_i_st = Input(UInt(1.W))
val longp_excp_i_buserr = Input(UInt(1.W))
val longp_excp_i_insterr = Input(UInt(1.W))
val longp_excp_i_badaddr = Input(UInt(p.E203_ADDR_SIZE.W))
val longp_excp_i_pc = Input(UInt(p.E203_PC_SIZE.W))
}
class E203_EXU_IRQ_EXCP_INTF (val p : EXCP_PARAM) extends Bundle{
val excpirq_flush_ack = Input(UInt(1.W))
val excpirq_flush_req = Output(UInt(1.W))
val nonalu_excpirq_flush_req_raw = Output(UInt(1.W))
val excpirq_flush_add_op1 = Output(UInt(p.E203_PC_SIZE.W))
val excpirq_flush_add_op2 = Output(UInt(p.E203_PC_SIZE.W))
val dbg_irq_r = Input(UInt(1.W))
val lcl_irq_r = Input(UInt(p.E203_LIRQ_NUM.W))
val ext_irq_r = Input(UInt(1.W))
val sft_irq_r = Input(UInt(1.W))
val tmr_irq_r = Input(UInt(1.W))
}
class E203_EXU_CMT_EXCP_INTF (val p : EXCP_PARAM) extends Bundle{
val csr_mtvec_r = Input(UInt(p.E203_XLEN.W))
val cmt_dret_ena = Input(UInt(1.W))
val cmt_ena = Input(UInt(1.W))
val cmt_badaddr = Output(UInt(p.E203_ADDR_SIZE.W))
val cmt_epc = Output(UInt(p.E203_PC_SIZE.W))
val cmt_cause = Output(UInt(p.E203_XLEN.W))
val cmt_badaddr_ena = Output(UInt(1.W))
val cmt_epc_ena = Output(UInt(1.W))
val cmt_cause_ena = Output(UInt(1.W))
val cmt_status_ena = Output(UInt(1.W))
val cmt_dpc = Output(UInt(p.E203_PC_SIZE.W))
val cmt_dpc_ena = Output(UInt(1.W))
val cmt_dcause = Output(UInt(3.W))
val cmt_dcause_ena = Output(UInt(1.W))
}
class E203_EXU_MIE_EXCP_INTF extends Bundle{
val status_mie_r = Input(UInt(1.W))
val mtie_r = Input(UInt(1.W))
val msie_r = Input(UInt(1.W))
val meie_r = Input(UInt(1.W))
}
class E203_EXU_DBG_EXCP_INTF extends Bundle{
val dbg_mode = Input(UInt(1.W))
val dbg_halt_r = Input(UInt(1.W))
val dbg_step_r = Input(UInt(1.W))
val dbg_ebreakm_r = Input(UInt(1.W))
}
class E203_EXU_MODE_EXCP_INTF extends Bundle{
val u_mode = Input(UInt(1.W))
val s_mode = Input(UInt(1.W))
val h_mode = Input(UInt(1.W))
val m_mode = Input(UInt(1.W))
}
class E203_EXU_EXCP (val p : EXCP_PARAM) extends Module{
val io = IO{new Bundle {
val wfi = new E203_EXU_WFI_EXCP_INTF
val alu = new E203_EXU_ALU_EXCP_INTF(p)
val longp = new E203_EXU_LONGP_EXCP_INTF(p)
val irq = new E203_EXU_IRQ_EXCP_INTF(p)
val cmt = new E203_EXU_CMT_EXCP_INTF(p)
val mie = new E203_EXU_MIE_EXCP_INTF
val dbg = new E203_EXU_DBG_EXCP_INTF
val mode = new E203_EXU_MODE_EXCP_INTF
val commit_trap = Output(UInt(1.W))
val amo_wait = Input(UInt(1.W))
val oitf_empty = Input(UInt(1.W))
val excp_active = Output(UInt(1.W))
}}
val irq_req_active = Wire(UInt(1.W))
val nonalu_dbg_entry_req_raw = Wire(UInt(1.W))
io.excp_active := irq_req_active | nonalu_dbg_entry_req_raw
val wfi_req_hsked = io.wfi.wfi_halt_ifu_req & io.wfi.wfi_halt_ifu_ack & io.wfi.wfi_halt_exu_req & io.wfi.wfi_halt_exu_ack
val wfi_flag_set = wfi_req_hsked
val wfi_irq_req = Wire(UInt(1.W))
val dbg_entry_req = Wire(UInt(1.W))
val wfi_flag_clr = wfi_irq_req | dbg_entry_req
val wfi_flag_nxt = wfi_flag_set & (!wfi_flag_clr)
val wfi_flag_ena = wfi_flag_set | wfi_flag_clr
val wfi_flag_r = RegEnable(wfi_flag_nxt,0.U(1.W),wfi_flag_ena.asBool)
io.wfi.core_wfi := wfi_flag_r & (!wfi_flag_clr)
val wfi_cmt_ena = io.alu.alu_excp_i_wfi & io.cmt.cmt_ena
val wfi_halt_req_set = wfi_cmt_ena & (!io.dbg.dbg_mode)
val wfi_halt_req_clr = wfi_flag_clr
val wfi_halt_req_ena = wfi_halt_req_set | wfi_halt_req_clr
val wfi_halt_req_nxt = wfi_halt_req_set & (!wfi_halt_req_clr)
val wfi_halt_req_r = RegEnable(wfi_halt_req_nxt,0.U(1.W),wfi_halt_req_ena.asBool)
io.wfi.wfi_halt_ifu_req := wfi_halt_req_r & (!wfi_halt_req_clr)
io.wfi.wfi_halt_exu_req := wfi_halt_req_r
//IRQ LOGIC
val irq_req = Wire(UInt(1.W))
val longp_need_flush = Wire(UInt(1.W))
val alu_need_flush = Wire(UInt(1.W))
val dbg_ebrk_req = Wire(UInt(1.W))
val dbg_trig_req = Wire(UInt(1.W))
val longp_excp_flush_req = longp_need_flush
io.longp.longp_excp_i_ready := io.irq.excpirq_flush_ack
val dbg_entry_flush_req = dbg_entry_req & io.oitf_empty & io.alu.alu_excp_i_pc_vld & (!longp_need_flush)
val alu_excp_i_ready4dbg = io.irq.excpirq_flush_ack & io.oitf_empty & io.alu.alu_excp_i_pc_vld & (!longp_need_flush)
val irq_flush_req = irq_req & io.oitf_empty & io.alu.alu_excp_i_pc_vld & (!dbg_entry_req) & (!longp_need_flush)
val alu_excp_flush_req = io.alu.alu_excp_i_valid & alu_need_flush & io.oitf_empty & (!irq_req) & (!dbg_entry_req) & (!longp_need_flush)
val nonalu_dbg_entry_req = Wire(UInt(1.W))
val alu_excp_i_ready4nodbg = Mux(alu_need_flush.asBool,(io.irq.excpirq_flush_ack & io.oitf_empty & (!irq_req) & (!nonalu_dbg_entry_req) & (!longp_need_flush)),((!irq_req) & (!nonalu_dbg_entry_req) & (!longp_need_flush)))
val alu_ebreakm_flush_req_novld = Wire(UInt(1.W))
val alu_dbgtrig_flush_req_novld = 0.U(1.W)
io.alu.alu_excp_i_ready := Mux((alu_ebreakm_flush_req_novld | alu_dbgtrig_flush_req_novld).asBool,alu_excp_i_ready4dbg,alu_excp_i_ready4nodbg)
io.irq.excpirq_flush_req := longp_excp_flush_req | dbg_entry_flush_req | irq_flush_req | alu_excp_flush_req
val all_excp_flush_req = longp_excp_flush_req | alu_excp_flush_req
io.irq.nonalu_excpirq_flush_req_raw := longp_need_flush | nonalu_dbg_entry_req_raw | irq_req
val excpirq_taken_ena = io.irq.excpirq_flush_req & io.irq.excpirq_flush_ack
io.commit_trap := excpirq_taken_ena
val excp_taken_ena = all_excp_flush_req & excpirq_taken_ena
val irq_taken_ena = irq_flush_req & excpirq_taken_ena
val dbg_entry_taken_ena = dbg_entry_flush_req & excpirq_taken_ena
io.irq.excpirq_flush_add_op1 := Mux(dbg_entry_flush_req.asBool,Fill(p.E203_PC_SIZE,0x800.U),Mux((all_excp_flush_req & io.dbg.dbg_mode).asBool,Fill(p.E203_PC_SIZE,0x808.U),io.cmt.csr_mtvec_r))
io.irq.excpirq_flush_add_op2 := Mux(dbg_entry_flush_req.asBool,Fill(p.E203_PC_SIZE,0.U),Mux((all_excp_flush_req & io.dbg.dbg_mode).asBool,Fill(p.E203_PC_SIZE,0.U),io.cmt.csr_mtvec_r))
longp_need_flush := io.longp.longp_excp_i_valid
//Debug Mode entry triggered Exception
val alu_ebreakm_flush_req = Wire(UInt(1.W))
val alu_dbgtrig_flush_req = 0.U(1.W)
val step_req_set = (!io.dbg.dbg_mode) & io.dbg.dbg_step_r & io.cmt.cmt_ena & (!dbg_entry_taken_ena)
val step_req_clr = dbg_entry_taken_ena
val step_req_ena = step_req_set | step_req_clr
val step_req_nxt = step_req_set | (!step_req_clr)
val step_req_r = RegEnable(step_req_nxt,0.U(1.W),step_req_ena.asBool)
val dbg_step_req = step_req_r
dbg_trig_req := alu_dbgtrig_flush_req & (!step_req_r)
dbg_ebrk_req := alu_ebreakm_flush_req & (!alu_dbgtrig_flush_req) & (!step_req_r)
val dbg_irq_req = io.irq.dbg_irq_r & (!alu_ebreakm_flush_req) & (!alu_dbgtrig_flush_req) & (!step_req_r)
val nonalu_dbg_irq_req = dbg_irq_req & (!step_req_r)
val dbg_halt_req = io.dbg.dbg_halt_r & (!dbg_irq_req) & (!alu_ebreakm_flush_req) & (!alu_ebreakm_flush_req) & (!step_req_r) & (!io.dbg.dbg_step_r)
val nonalu_dbg_halt_req = io.dbg.dbg_halt_r & (!io.irq.dbg_irq_r) & (!step_req_r) & (!io.dbg.dbg_step_r)
val dbg_entry_mask = io.dbg.dbg_mode
dbg_entry_req := (!dbg_entry_mask) & ((dbg_irq_req & (!io.amo_wait)) | (dbg_halt_req & (!io.amo_wait)) | dbg_step_req | (dbg_trig_req & (!io.amo_wait)) | dbg_ebrk_req)
nonalu_dbg_entry_req := (!dbg_entry_mask) & ((nonalu_dbg_irq_req & (!io.amo_wait)) | (nonalu_dbg_halt_req & (!io.amo_wait)) | dbg_step_req)
nonalu_dbg_entry_req_raw := (!dbg_entry_mask) & (io.irq.dbg_irq_r | io.dbg.dbg_halt_r | step_req_r)
//IRQ Triggered Exception
val irq_mask = io.dbg.dbg_mode | io.dbg.dbg_step_r | (!io.mie.status_mie_r)
val wfi_irq_mask = io.dbg.dbg_mode | io.dbg.dbg_step_r
val irq_req_raw = (io.irq.ext_irq_r & io.mie.meie_r) | (io.irq.sft_irq_r & io.mie.msie_r) | (io.irq.tmr_irq_r & io.mie.mtie_r)
irq_req := (!irq_mask) & irq_req_raw
wfi_irq_req := (!wfi_irq_mask) & irq_req_raw
irq_req_active := Mux(wfi_flag_r.asBool,wfi_irq_req,irq_req)
val irq_cause = Wire(UInt(p.E203_XLEN.W))
irq_cause := Cat(1.U(1.W),0.U(27.W),Mux((io.irq.sft_irq_r & io.mie.msie_r).asBool,3.U(4.W),Mux((io.irq.tmr_irq_r & io.mie.mtie_r).asBool,7.U(4.W),Mux((io.irq.ext_irq_r & io.mie.meie_r).asBool,11.U(4.W),0.U(4.W)))))
//irq_cause(31,31) := 1.U(1.W)
//irq_cause(30,4) := 0.U(27.W)
//irq_cause(3,0) := Mux((io.irq.sft_irq_r & io.mie.msie_r).asBool,3.U(4.W),Mux((io.irq.tmr_irq_r & io.mie.mtie_r).asBool,7.U(4.W),Mux((io.irq.ext_irq_r & io.mie.meie_r).asBool,11.U(4.W),0.U(4.W))))
//ALU Triggered Exception
val alu_excp_i_ebreak4excp = io.alu.alu_excp_i_ebreak & ((!io.dbg.dbg_ebreakm_r) | io.dbg.dbg_mode)
val alu_excp_i_ebreak4dbg = io.alu.alu_excp_i_ebreak & (!alu_need_flush) & io.dbg.dbg_ebreakm_r & (!io.dbg.dbg_mode)
alu_ebreakm_flush_req := io.alu.alu_excp_i_valid & alu_excp_i_ebreak4dbg
alu_ebreakm_flush_req_novld := alu_excp_i_ebreak4dbg
alu_need_flush := io.alu.alu_excp_i_misalgn | io.alu.alu_excp_i_buserr | alu_excp_i_ebreak4excp | io.alu.alu_excp_i_ecall | io.alu.alu_excp_i_ifu_misalgn | io.alu.alu_excp_i_ifu_buserr | io.alu.alu_excp_i_ifu_ilegl
//Update the CSRs
val longp_excp_flush_req_ld = longp_excp_flush_req & io.longp.longp_excp_i_ld
val longp_excp_flush_req_st = longp_excp_flush_req & io.longp.longp_excp_i_st
val longp_excp_flush_req_insterr = longp_excp_flush_req & io.longp.longp_excp_i_insterr
val alu_excp_flush_req_ld = alu_excp_flush_req & io.alu.alu_excp_i_ld
val alu_excp_flush_req_stamo = alu_excp_flush_req & io.alu.alu_excp_i_stamo
val alu_excp_flush_req_ebreak = alu_excp_flush_req & alu_excp_i_ebreak4excp
val alu_excp_flush_req_ecall = alu_excp_flush_req & io.alu.alu_excp_i_ecall
val alu_excp_flush_req_ifu_misalgn = alu_excp_flush_req & io.alu.alu_excp_i_ifu_misalgn
val alu_excp_flush_req_ifu_buserr = alu_excp_flush_req & io.alu.alu_excp_i_ifu_buserr
val alu_excp_flush_req_ifu_ilegl = alu_excp_flush_req & io.alu.alu_excp_i_ifu_ilegl
val alu_excp_flush_req_ld_misalgn = alu_excp_flush_req_ld & io.alu.alu_excp_i_misalgn
val alu_excp_flush_req_ld_buserr = alu_excp_flush_req_ld & io.alu.alu_excp_i_buserr
val alu_excp_flush_req_stamo_misalgn = alu_excp_flush_req_stamo & io.alu.alu_excp_i_misalgn
val alu_excp_flush_req_stamo_buserr = alu_excp_flush_req_stamo & io.alu.alu_excp_i_buserr
val longp_excp_flush_req_ld_buserr = longp_excp_flush_req_ld & io.longp.longp_excp_i_buserr
val longp_excp_flush_req_st_buserr = longp_excp_flush_req_st & io.longp.longp_excp_i_buserr
val excp_flush_by_alu_agu = alu_excp_flush_req_ld_misalgn | alu_excp_flush_req_ld_buserr | alu_excp_flush_req_stamo_misalgn | alu_excp_flush_req_stamo_buserr
val excp_flush_by_longp_ldst = longp_excp_flush_req_ld_buserr | longp_excp_flush_req_st_buserr
val excp_cause = Wire(UInt(p.E203_XLEN.W))
excp_cause := Cat(0.U(27.W), Mux(alu_excp_flush_req_ifu_misalgn.asBool, 0.U(5.W),
Mux(alu_excp_flush_req_ifu_buserr.asBool, 1.U(5.W),
Mux(alu_excp_flush_req_ifu_ilegl.asBool, 2.U(5.W),
Mux(alu_excp_flush_req_ebreak.asBool, 3.U(5.W),
Mux(alu_excp_flush_req_ld_misalgn.asBool, 4.U(5.W),
Mux((longp_excp_flush_req_ld_buserr | alu_excp_flush_req_ld_buserr).asBool, 5.U(5.W),
Mux(alu_excp_flush_req_stamo_misalgn.asBool, 6.U(5.W),
Mux((longp_excp_flush_req_st_buserr | alu_excp_flush_req_stamo_buserr).asBool, 7.U(5.W),
Mux((alu_excp_flush_req_ecall & io.mode.u_mode).asBool, 8.U(5.W),
Mux((alu_excp_flush_req_ecall | io.mode.s_mode).asBool, 9.U(5.W),
Mux((alu_excp_flush_req_ecall | io.mode.h_mode).asBool, 10.U(5.W),
Mux((alu_excp_flush_req_ecall | io.mode.m_mode).asBool, 11.U(5.W),
Mux(longp_excp_flush_req_insterr.asBool, 16.U(5.W),
31.U(5.W)))))))))))))))
//excp_cause(31,5) := 0.U(27.W)
//excp_cause(4,0) := Mux(alu_excp_flush_req_ifu_misalgn.asBool,0.U(5.W),
// Mux(alu_excp_flush_req_ifu_buserr.asBool,1.U(5.W),
// Mux(alu_excp_flush_req_ifu_ilegl.asBool,2.U(5.W),
// Mux(alu_excp_flush_req_ebreak.asBool,3.U(5.W),
// Mux(alu_excp_flush_req_ld_misalgn.asBool,4.U(5.W),
// Mux((longp_excp_flush_req_ld_buserr | alu_excp_flush_req_ld_buserr).asBool,5.U(5.W),
// Mux(alu_excp_flush_req_stamo_misalgn.asBool,6.U(5.W),
// Mux((longp_excp_flush_req_st_buserr | alu_excp_flush_req_stamo_buserr).asBool,7.U(5.W),
// Mux((alu_excp_flush_req_ecall & io.mode.u_mode).asBool,8.U(5.W),
// Mux((alu_excp_flush_req_ecall | io.mode.s_mode).asBool,9.U(5.W),
// Mux((alu_excp_flush_req_ecall | io.mode.h_mode).asBool,10.U(5.W),
// Mux((alu_excp_flush_req_ecall | io.mode.m_mode).asBool,11.U(5.W),
// Mux(longp_excp_flush_req_insterr.asBool,16.U(5.W),
// 31.U(5.W))))))))))))))
//Bad Address
val excp_flush_req_ld_misalgn = alu_excp_flush_req_ld_misalgn
val excp_flush_req_ld_buserr = alu_excp_flush_req_ld_buserr | longp_excp_flush_req_ld_buserr
val cmt_badaddr_update = io.irq.excpirq_flush_req
io.cmt.cmt_badaddr := Mux(excp_flush_by_longp_ldst.asBool, io.longp.longp_excp_i_badaddr,
Mux(excp_flush_by_alu_agu.asBool,io.alu.alu_excp_i_badaddr,
Mux((alu_excp_flush_req_ebreak | alu_excp_flush_req_ifu_misalgn | alu_excp_flush_req_ifu_buserr).asBool,io.alu.alu_excp_i_pc,
Mux(alu_excp_flush_req_ifu_ilegl.asBool,io.alu.alu_excp_i_instr,
Fill(p.E203_ADDR_SIZE,0.U)))))
io.cmt.cmt_epc := Mux(io.longp.longp_excp_i_valid.asBool,io.longp.longp_excp_i_pc,io.alu.alu_excp_i_pc)
io.cmt.cmt_cause := Mux(excp_taken_ena.asBool,excp_cause,irq_cause)
io.cmt.cmt_epc_ena := (!io.dbg.dbg_mode) & (excp_taken_ena | irq_taken_ena)
io.cmt.cmt_cause_ena := io.cmt.cmt_epc_ena
io.cmt.cmt_status_ena := io.cmt.cmt_epc_ena
io.cmt.cmt_badaddr_ena := io.cmt.cmt_epc_ena & cmt_badaddr_update
io.cmt.cmt_dpc := io.alu.alu_excp_i_pc
io.cmt.cmt_dpc_ena := dbg_entry_taken_ena
val cmt_dcause_set = dbg_entry_taken_ena
val cmt_dcause_clr = io.cmt.cmt_dret_ena
val set_dcause_nxt = Wire(UInt(3.W))
set_dcause_nxt := Mux(dbg_trig_req.asBool,2.U(3.W),
Mux(dbg_ebrk_req.asBool,1.U(3.W),
Mux(dbg_irq_req.asBool,3.U(3.W),
Mux(dbg_step_req.asBool,4.U(3.W),
Mux(dbg_halt_req.asBool,5.U(3.W),
0.U(3.W))))))
io.cmt.cmt_dcause_ena := cmt_dcause_set | cmt_dcause_clr
io.cmt.cmt_dcause := Mux(cmt_dcause_set.asBool,set_dcause_nxt,0.U(3.W))
}
object E203_EXU_EXCP_Gen extends App{
(new chisel3.stage.ChiselStage).execute(Array("--target-dir","generated/E203"),Seq(ChiselGeneratorAnnotation(() => new E203_EXU_EXCP(new EXCP_PARAM(32,32,32,32,1)))))
}
自己尝试写下E203的RISC-V异常中断检测的chisel代码
仅供参考,功能不保证