xref: /XiangShan/src/main/scala/xiangshan/cache/CacheInstruction.scala (revision 77decb47ed7c3b4a06d0628697e1586df7c7de6e)
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