quasar/src/main/scala/ifu/el2_ifu_ic_mem.scala

176 lines
7.5 KiB
Scala

package ifu
import lib._
import chisel3._
import chisel3.util._
class el2_ifu_ic_mem extends Module with param{
val io = IO(new Bundle{
val clk = Input(Bool())
val rst_l = Input(Bool())
val clk_override = Input(Bool())
val dec_tlu_core_ecc_disable = Input(Bool())
val ic_rw_addr = Input(UInt(31.W))
val ic_wr_en = Input(UInt(ICACHE_NUM_WAYS.W))
val ic_rd_en = Input(Bool())
val ic_debug_addr = Input(UInt((ICACHE_INDEX_HI-3).W))
val ic_debug_rd_en = Input(Bool())
val ic_debug_wr_en = Input(Bool())
val ic_debug_tag_array = Input(Bool())
val ic_debug_way = Input(UInt(ICACHE_NUM_WAYS.W))
val ic_premux_data = Input(UInt(64.W))
val ic_sel_premux_data = Input(Bool())
val ic_wr_data = Vec(ICACHE_BANKS_WAY, Input(UInt(71.W)))
val ic_rd_data = Output(UInt(64.W))
val ic_debug_rd_data = Output(UInt(71.W))
val ictag_debug_rd_data = Output(UInt(26.W))
val ic_debug_wr_data = Input(UInt(71.W))
val ic_eccerr = Output(UInt(ICACHE_BANKS_WAY.W))
val ic_parerr = Output(UInt(ICACHE_BANKS_WAY.W))
val ic_tag_valid = Input(UInt(ICACHE_NUM_WAYS.W))
val ic_rd_hit = Output(UInt(ICACHE_NUM_WAYS.W))
val ic_tag_perr = Output(Bool())
val scan_mode = Input(Bool())
})
io.ic_tag_perr := 0.U
io.ic_rd_hit := 0.U
io.ic_parerr := 0.U
io.ic_eccerr := 0.U
io.ictag_debug_rd_data := 0.U
io.ic_debug_rd_data := 0.U
io.ic_rd_data := 0.U
//val icache_tag = Module(new kncpa)
}
/////////// ICACHE TAG
class EL2_IC_TAG extends Module with el2_lib with param {
val io = IO(new Bundle{
val clk = Input(Bool())
val rst_l = Input(Bool())
val clk_override = Input(Bool())
val dec_tlu_core_ecc_disable = Input(Bool())
val ic_rw_addr = Input(UInt(32.W)) // TODO : In SV we have 31:3 what should we do here
val ic_wr_en = Input(UInt(ICACHE_NUM_WAYS.W))
val ic_tag_valid = Input(UInt(ICACHE_NUM_WAYS.W))
val ic_rd_en = Input(Bool())
val ic_debug_addr = Input(UInt((ICACHE_INDEX_HI+1).W))
val ic_debug_rd_en = Input(Bool())
val ic_debug_wr_en = Input(Bool())
val ic_debug_tag_array = Input(Bool())
val ic_debug_way = Input(UInt(ICACHE_NUM_WAYS.W))
val ictag_debug_rd_data = Output(UInt(26.W))
val ic_debug_wr_data = Input(UInt(71.W))
val ic_rd_hit = Output(UInt(ICACHE_NUM_WAYS.W))
val ic_tag_perr = Output(Bool())
val scan_mode = Input(Bool())
val test = Output(Vec(ICACHE_NUM_WAYS, UInt(26.W)))
val test_ecc_data_out = Output(Vec(ICACHE_NUM_WAYS,UInt(32.W)))
val test_ecc_out = Output(Vec(ICACHE_NUM_WAYS,UInt(7.W)))
val test_ecc_sb_out = Output(Vec(ICACHE_NUM_WAYS,UInt(1.W)))
val test_ecc_db_out = Output(Vec(ICACHE_NUM_WAYS,UInt(1.W)))
})
val ic_tag_wren = io.ic_wr_en & repl(ICACHE_NUM_WAYS, io.ic_rw_addr(ICACHE_BEAT_ADDR_HI,4)===
repl(ICACHE_NUM_WAYS-1, 1.U))
val ic_debug_rd_way_en = repl(ICACHE_NUM_WAYS, io.ic_debug_rd_en & io.ic_debug_tag_array) & io.ic_debug_way
val ic_debug_wr_way_en = repl(ICACHE_NUM_WAYS, io.ic_debug_wr_en & io.ic_debug_tag_array) & io.ic_debug_way
val ic_tag_clken = repl(ICACHE_NUM_WAYS,io.ic_rd_en | io.clk_override) | io.ic_wr_en | ic_debug_wr_way_en |
ic_debug_rd_way_en
val ic_rd_en_ff = RegNext(io.ic_rd_en, init=0.U)
val ic_rw_addr_ff = RegNext(io.ic_rw_addr(31,ICACHE_TAG_LO))
val PAD_BITS = 21 - (32 - ICACHE_TAG_LO)
val ic_tag_wren_q = ic_tag_wren | ic_debug_wr_way_en
val ic_tag_ecc = Wire(UInt(7.W))
val ic_tag_wr_data = Wire(UInt(26.W))
val ic_tag_parity = Wire(UInt(1.W))
ic_tag_ecc := 0.U
ic_tag_wr_data := 0.U
ic_tag_parity := 0.U
when((ICACHE_TAG_LO == 11).B){
when(ICACHE_ECC.B){
ic_tag_ecc := rvecc_encode(Cat(repl(ICACHE_TAG_LO,0.U) , io.ic_rw_addr(31,ICACHE_TAG_LO)))
ic_tag_wr_data := Mux(io.ic_debug_wr_en & io.ic_debug_tag_array,
Cat(io.ic_debug_wr_data(68,64), io.ic_debug_wr_data(31,11)) ,
Cat(ic_tag_ecc(4,0), io.ic_rw_addr(31,ICACHE_TAG_LO)))
}
.otherwise{
ic_tag_parity := rveven_paritygen(io.ic_rw_addr(31,ICACHE_TAG_LO))
ic_tag_wr_data := Mux(io.ic_debug_wr_en & io.ic_debug_tag_array,
Cat(io.ic_debug_wr_data(68,64), io.ic_debug_wr_data(31,11)) ,
Cat(ic_tag_ecc(4,0), io.ic_rw_addr(31,ICACHE_TAG_LO)))
}
}
.otherwise{
when(ICACHE_ECC.B){
ic_tag_ecc := rvecc_encode(Cat(repl(ICACHE_TAG_LO,0.U) , io.ic_rw_addr(31,ICACHE_TAG_LO)))
ic_tag_wr_data := Mux(io.ic_debug_wr_en & io.ic_debug_tag_array,
Cat(io.ic_debug_wr_data(68,64), io.ic_debug_wr_data(31,11)) ,
Cat(ic_tag_ecc(4,0), repl(PAD_BITS,0.U), io.ic_rw_addr(31,ICACHE_TAG_LO)))
}
.otherwise{
ic_tag_parity := rveven_paritygen(io.ic_rw_addr(31,ICACHE_TAG_LO))
ic_tag_wr_data := Mux(io.ic_debug_wr_en & io.ic_debug_tag_array,
Cat(io.ic_debug_wr_data(68,64), io.ic_debug_wr_data(31,11)) ,
Cat(ic_tag_ecc(4,0), repl(PAD_BITS,0.U), io.ic_rw_addr(31,ICACHE_TAG_LO)))
}
}
val ic_rw_addr_q = Mux(io.ic_debug_rd_en | io.ic_debug_wr_en,
io.ic_debug_addr(ICACHE_INDEX_HI, ICACHE_TAG_INDEX_LO),
io.ic_rw_addr(ICACHE_INDEX_HI, ICACHE_TAG_INDEX_LO))
val ic_debug_rd_way_en_ff = RegNext(io.ic_debug_rd_en, init = 0.U)
val ic_way_tag = if(ICACHE_ECC) SyncReadMem(ICACHE_TAG_DEPTH, Vec(ICACHE_NUM_WAYS, UInt(26.W)))
else SyncReadMem(ICACHE_TAG_DEPTH, Vec(ICACHE_NUM_WAYS, UInt(22.W)))
//val ic_tag_data_raw = if(ICACHE_ECC) Vec(ICACHE_NUM_WAYS, UInt(26.W)) else Vec(ICACHE_NUM_WAYS, UInt(22.W))
val write_data = VecInit.tabulate(ICACHE_NUM_WAYS)(i => ic_tag_wr_data)
val mem_mask = VecInit.tabulate(ICACHE_NUM_WAYS)(i => ic_tag_wren_q(i) & ic_tag_clken(i))
ic_way_tag.write(ic_rw_addr_q, write_data, mem_mask)
val ic_tag_data_raw = ic_way_tag.read(ic_rw_addr_q, 1.B)
//val w_tout = Wire(UInt(32.W))
val w_tout = if(ICACHE_ECC)ic_tag_data_raw.map(x=>Cat(ic_tag_data_raw(x)(25,21),ic_tag_data_raw(x)(31-ICACHE_TAG_LO,0),0.U(13.W)))
else ic_tag_data_raw.map(x=>Cat(0.U(4.W),ic_tag_data_raw(x)(32),ic_tag_data_raw(x)(31-ICACHE_TAG_LO,0),0.U(13.W)))
val ecc_decode = new Array[rvecc_decode](ICACHE_NUM_WAYS)
val parcheck = new Array[UInt](ICACHE_NUM_WAYS)
val ic_tag_corrected_data_unc = Wire(Vec(ICACHE_NUM_WAYS, UInt(32.W)))
val ic_tag_corrected_ecc_unc = Wire(Vec(ICACHE_NUM_WAYS, UInt(7.W)))
val ic_tag_single_ecc_error = Wire(Vec(ICACHE_NUM_WAYS, UInt(1.W)))
val ic_tag_double_ecc_error = Wire(Vec(ICACHE_NUM_WAYS, UInt(1.W)))
val ic_tag_way_perr = VecInit.tabulate(ICACHE_NUM_WAYS)(i => rveven_paritycheck(w_tout(i)(31,ICACHE_TAG_LO),w_tout(i)(31)))
for(i <- 0 until ICACHE_NUM_WAYS) {
ecc_decode(i) = Module(new rvecc_decode())
ecc_decode(i).io.en := ~io.dec_tlu_core_ecc_disable & ic_rd_en_ff
ecc_decode(i).io.sed_ded := 1.U
ecc_decode(i).io.din := Cat(0.U(11.W),ic_tag_data_raw(i)(20,0))
ecc_decode(i).io.ecc_in := Cat(0.U(2.W),ic_tag_data_raw(i)(25,21))
ic_tag_corrected_data_unc := io.test_ecc_data_out
ic_tag_corrected_ecc_unc := io.test_ecc_out
ic_tag_single_ecc_error := io.test_ecc_sb_out
ic_tag_double_ecc_error := io.test_ecc_db_out
io.test_ecc_data_out(i) := ecc_decode(i).io.dout
io.test_ecc_out(i) := ecc_decode(i).io.ecc_out
io.test_ecc_sb_out(i) := ecc_decode(i).io.single_ecc_error
io.test_ecc_db_out(i) := ecc_decode(i).io.double_ecc_error
ic_tag_way_perr(i) := ic_tag_single_ecc_error(i) | ic_tag_double_ecc_error(i)
}
io.test := w_tout
io.ic_tag_perr := 0.U
io.ic_rd_hit := 0.U
io.ictag_debug_rd_data := 0.U
}
object ifu_ic extends App {
println((new chisel3.stage.ChiselStage).emitVerilog(new EL2_IC_TAG()))
}