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