1package xiangshan.cache 2 3import chisel3._ 4import chisel3.util._ 5import xiangshan._ 6import xiangshan.frontend.icache._ 7import utils._ 8import chipsalliance.rocketchip.config.Parameters 9import xiangshan.backend.fu.util.HasCSRConst 10 11object CacheOpMap{ 12 def apply(opcode: String, optype: String, name: String ): Map[String, String] = { 13 Map( 14 "opcode" -> opcode, 15 "optype" -> optype, 16 "name" -> name, 17 ) 18 } 19} 20 21object CacheRegMap{ 22 def apply(offset: String, width: String, authority: String, name: String ): Pair[String, Map[String, String]] = { 23 name -> Map( 24 "offset" -> offset, 25 "width" -> width, 26 "authority" -> authority, 27 ) 28 } 29} 30 31trait CacheControlConst{ 32 def maxDataRowSupport = 8 33} 34 35abstract class CacheCtrlModule(implicit p: Parameters) extends XSModule with HasCSRConst with CacheControlConst 36 37object CacheInstrucion{ 38 def CacheOperation = List( 39 CacheOpMap("b00000", "CHECK", "READ_TAG_ECC"), 40 CacheOpMap("b00001", "CHECK", "READ_DATA_ECC"), 41 CacheOpMap("b00010", "LOAD", "READ_TAG"), 42 CacheOpMap("b00011", "LOAD", "READ_DATA"), 43 CacheOpMap("b00100", "STORE", "WRITE_TAG_ECC"), 44 CacheOpMap("b00101", "STORE", "WRITE_DATA_ECC"), 45 CacheOpMap("b00110", "STORE", "WRITE_TAG"), 46 CacheOpMap("b00111", "STORE", "WRITE_DATA"), 47 CacheOpMap("b01000", "FLUSH", "FLUSH_BLOCK") 48 ) 49 50 def CacheInsRegisterList = Map( 51 // offset width authority name 52 CacheRegMap("0", "64", "RW", "CACHE_OP"), 53 CacheRegMap("1", "64", "RW", "OP_FINISH"), 54 CacheRegMap("2", "64", "RW", "CACHE_LEVEL"), 55 CacheRegMap("3", "64", "RW", "CACHE_WAY"), 56 CacheRegMap("4", "64", "RW", "CACHE_IDX"), 57 CacheRegMap("5", "64", "RW", "CACHE_BANK_NUM"), 58 CacheRegMap("6", "64", "RW", "CACHE_TAG_ECC"), 59 CacheRegMap("7", "64", "RW", "CACHE_TAG_BITS"), // TODO 60 CacheRegMap("8", "64", "RW", "CACHE_TAG_LOW"), 61 CacheRegMap("9", "64", "RW", "CACHE_TAG_HIGH"), // not used in 64 bit arch 62 CacheRegMap("10", "64", "RW", "CACHE_ECC_WIDTH"), // TODO 63 CacheRegMap("11", "64", "RW", "CACHE_DATA_ECC"), 64 CacheRegMap("12", "64", "RW", "CACHE_DATA_0"), 65 CacheRegMap("13", "64", "RW", "CACHE_DATA_1"), 66 CacheRegMap("14", "64", "RW", "CACHE_DATA_2"), 67 CacheRegMap("15", "64", "RW", "CACHE_DATA_3"), 68 CacheRegMap("16", "64", "RW", "CACHE_DATA_4"), 69 CacheRegMap("17", "64", "RW", "CACHE_DATA_5"), 70 CacheRegMap("18", "64", "RW", "CACHE_DATA_6"), 71 CacheRegMap("19", "64", "RW", "CACHE_DATA_7"), 72 ) 73 74 // Usage: 75 // val cacheopMapping = CacheInstrucion.CacheInsRegisterList.map{case (name, attribute) => { 76 // doSthWith(name, attribute("offset"), attribute("width")) 77 // }} 78 79 def COP_CHECK = 0.U 80 def COP_LOAD = 1.U 81 def COP_STORE = 2.U 82 def COP_FLUSH = 3.U 83 84 def COP_ID_ICACHE = 0 85 def COP_ID_DCACHE = 1 86 87 def COP_RESULT_CODE_IDLE = 0.U 88 def COP_RESULT_CODE_OK = 1.U 89 def COP_RESULT_CODE_ERROR = 2.U 90 91 def isReadTagECC(opcode: UInt) = opcode === "b00000".U 92 def isReadDataECC(opcode: UInt) = opcode === "b00001".U 93 def isReadTag(opcode: UInt) = opcode === "b00010".U 94 def isReadData(opcode: UInt) = opcode === "b00011".U 95 def isWriteTagECC(opcode: UInt) = opcode === "b00100".U 96 def isWriteDataECC(opcode: UInt) = opcode === "b00101".U 97 def isWriteTag(opcode: UInt) = opcode === "b00110".U 98 def isWriteData(opcode: UInt) = opcode === "b00111".U 99 def isFlush(opcode: UInt) = opcode === "b01000".U 100 101 def isReadOp(opcode: UInt) = isReadTagECC(opcode) || 102 isReadDataECC(opcode) || 103 isReadTag(opcode) || 104 isReadData(opcode) 105} 106 107class CacheCtrlReqInfo(implicit p: Parameters) extends XSBundle with CacheControlConst { 108 val level = UInt(XLEN.W) // op target id 109 val wayNum = UInt(XLEN.W) 110 val index = UInt(XLEN.W) 111 val opCode = UInt(XLEN.W) 112 val write_tag_high = UInt(XLEN.W) 113 val write_tag_low = UInt(XLEN.W) 114 val write_tag_ecc = UInt(XLEN.W) 115 val write_data_vec = Vec(maxDataRowSupport, UInt(XLEN.W)) 116 val write_data_ecc = UInt(XLEN.W) 117 val bank_num = UInt(XLEN.W) 118} 119 120class CacheCtrlRespInfo(implicit p: Parameters) extends XSBundle with HasICacheParameters with CacheControlConst{ 121 val read_tag_high = UInt(XLEN.W) 122 val read_tag_low = UInt(XLEN.W) 123 val read_tag_ecc = UInt(XLEN.W) 124 val read_data_vec = Vec(maxDataRowSupport, UInt(XLEN.W)) 125 val read_data_ecc = UInt(XLEN.W) 126 val bank_num = UInt(XLEN.W) 127} 128 129class L1CacheToCsrIO(implicit p: Parameters) extends DCacheBundle { 130 val distribute_csr = Flipped(new DistributedCSRIO) 131 val update = new DistributedCSRUpdateReq 132} 133 134class DCacheInnerOpIO(implicit p: Parameters) extends DCacheBundle { 135 val req = Valid(new CacheCtrlReqInfo) 136 val resp = Flipped(Valid(new CacheCtrlRespInfo)) 137} 138 139class CSRCacheOpDecoder(decoder_name: String, id: Int)(implicit p: Parameters) extends CacheCtrlModule { 140 val io = IO(new Bundle { 141 val csr = new L1CacheToCsrIO 142 val cache = new DCacheInnerOpIO 143 }) 144 145 // CSRCacheOpDecoder state 146 val wait_csr_op_req = RegInit(true.B) // waiting for csr "CACHE_OP" being write 147 val wait_cache_op_resp = RegInit(false.B) // waiting for dcache to finish dcache op 148 val schedule_csr_op_resp_data = RegInit(false.B) // ready to write data readed from cache back to csr 149 val schedule_csr_op_resp_finish = RegInit(false.B) // ready to write "OP_FINISH" csr 150 // val cache_op_resp_timer = RegInit(0.U(4.W)) 151 val data_transfer_finished = WireInit(false.B) 152 val data_transfer_cnt = RegInit(0.U(log2Up(maxDataRowSupport).W)) 153 154 // Translate CSR write to cache op 155 val translated_cache_req = Reg(new CacheCtrlReqInfo) 156 println("Cache op decoder (" + decoder_name + "):") 157 println(" Id " + id) 158 // CacheInsRegisterList.map{case (name, attribute) => { 159 // println(" Register CSR mirror " + name) 160 // }} 161 162 def cacheop_csr_is_being_write(csr_name: String): Bool = { 163 io.csr.distribute_csr.w.bits.addr === (CacheInstrucion.CacheInsRegisterList(csr_name)("offset").toInt + Scachebase).U && 164 io.csr.distribute_csr.w.valid 165 } 166 167 def update_cache_req_when_write(csr_name: String, req_field: Data) = { 168 when( 169 cacheop_csr_is_being_write(csr_name) 170 ){ 171 req_field := io.csr.distribute_csr.w.bits.data 172 assert(wait_csr_op_req) 173 } 174 } 175 176 update_cache_req_when_write("CACHE_OP", translated_cache_req.opCode) 177 update_cache_req_when_write("CACHE_LEVEL", translated_cache_req.level) 178 update_cache_req_when_write("CACHE_WAY", translated_cache_req.wayNum) 179 update_cache_req_when_write("CACHE_IDX", translated_cache_req.index) 180 update_cache_req_when_write("CACHE_BANK_NUM", translated_cache_req.bank_num) 181 update_cache_req_when_write("CACHE_TAG_HIGH", translated_cache_req.write_tag_high) 182 update_cache_req_when_write("CACHE_TAG_LOW", translated_cache_req.write_tag_low) 183 update_cache_req_when_write("CACHE_TAG_ECC", translated_cache_req.write_tag_ecc) 184 update_cache_req_when_write("CACHE_DATA_0", translated_cache_req.write_data_vec(0)) 185 update_cache_req_when_write("CACHE_DATA_1", translated_cache_req.write_data_vec(1)) 186 update_cache_req_when_write("CACHE_DATA_2", translated_cache_req.write_data_vec(2)) 187 update_cache_req_when_write("CACHE_DATA_3", translated_cache_req.write_data_vec(3)) 188 update_cache_req_when_write("CACHE_DATA_4", translated_cache_req.write_data_vec(4)) 189 update_cache_req_when_write("CACHE_DATA_5", translated_cache_req.write_data_vec(5)) 190 update_cache_req_when_write("CACHE_DATA_6", translated_cache_req.write_data_vec(6)) 191 update_cache_req_when_write("CACHE_DATA_7", translated_cache_req.write_data_vec(7)) 192 update_cache_req_when_write("CACHE_DATA_ECC", translated_cache_req.write_data_ecc) 193 194 val cache_op_start = WireInit(cacheop_csr_is_being_write("CACHE_OP") && id.U === translated_cache_req.level) 195 when(cache_op_start) { 196 wait_csr_op_req := false.B 197 } 198 199 // Send cache op to cache 200 io.cache.req.valid := RegNext(cache_op_start) 201 io.cache.req.bits := translated_cache_req 202 when(io.cache.req.fire()){ 203 wait_cache_op_resp := true.B 204 } 205 206 // Receive cache op resp from cache 207 val raw_cache_resp = Reg(new CacheCtrlRespInfo) 208 when(io.cache.resp.fire()){ 209 wait_cache_op_resp := false.B 210 raw_cache_resp := io.cache.resp.bits 211 when(CacheInstrucion.isReadOp(translated_cache_req.opCode)){ 212 schedule_csr_op_resp_data := true.B 213 schedule_csr_op_resp_finish := false.B 214 assert(data_transfer_cnt === 0.U) 215 }.otherwise{ 216 schedule_csr_op_resp_data := false.B 217 schedule_csr_op_resp_finish := true.B 218 } 219 } 220 221 // Translate cache op resp to CSR write, send it back to CSR 222 when(io.csr.update.w.fire() && schedule_csr_op_resp_data && data_transfer_finished){ 223 schedule_csr_op_resp_data := false.B 224 schedule_csr_op_resp_finish := true.B 225 } 226 when(io.csr.update.w.fire() && schedule_csr_op_resp_finish){ 227 schedule_csr_op_resp_finish := false.B 228 wait_csr_op_req := true.B 229 } 230 231 io.csr.update.w.valid := schedule_csr_op_resp_data || schedule_csr_op_resp_finish 232 io.csr.update.w.bits := DontCare 233 234 val isReadTagECC = WireInit(CacheInstrucion.isReadTagECC(translated_cache_req.opCode)) 235 val isReadDataECC = WireInit(CacheInstrucion.isReadDataECC(translated_cache_req.opCode)) 236 val isReadTag = WireInit(CacheInstrucion.isReadTag(translated_cache_req.opCode)) 237 val isReadData = WireInit(CacheInstrucion.isReadData(translated_cache_req.opCode)) 238 239 when(schedule_csr_op_resp_data){ 240 io.csr.update.w.bits.addr := Mux1H(List( 241 isReadTagECC -> (CacheInstrucion.CacheInsRegisterList("CACHE_TAG_ECC")("offset").toInt + Scachebase).U, 242 isReadDataECC -> (CacheInstrucion.CacheInsRegisterList("CACHE_DATA_ECC")("offset").toInt + Scachebase).U, 243 isReadTag -> ((CacheInstrucion.CacheInsRegisterList("CACHE_TAG_LOW")("offset").toInt + Scachebase).U + data_transfer_cnt), 244 isReadData -> ((CacheInstrucion.CacheInsRegisterList("CACHE_DATA_0")("offset").toInt + Scachebase).U + data_transfer_cnt), 245 )) 246 io.csr.update.w.bits.data := Mux1H(List( 247 isReadTagECC -> raw_cache_resp.read_tag_ecc, 248 isReadDataECC -> raw_cache_resp.read_data_ecc, 249 isReadTag -> raw_cache_resp.read_tag_low, 250 isReadData -> raw_cache_resp.read_data_vec(data_transfer_cnt), 251 )) 252 data_transfer_finished := Mux(isReadData, 253 data_transfer_cnt === (maxDataRowSupport-1).U, 254 true.B 255 ) 256 data_transfer_cnt := data_transfer_cnt + 1.U 257 } 258 259 when(schedule_csr_op_resp_finish){ 260 io.csr.update.w.bits.addr := (CacheInstrucion.CacheInsRegisterList("OP_FINISH")("offset").toInt + Scachebase).U 261 io.csr.update.w.bits.data := CacheInstrucion.COP_RESULT_CODE_OK 262 data_transfer_cnt := 0.U 263 } 264} 265