ldu.scala 5.9 KB
Newer Older
1
package xiangshan.cache
A
Allen 已提交
2 3 4 5

import chisel3._
import chisel3.util._

6
import utils.XSDebug
A
Allen 已提交
7 8 9 10

class LoadPipe extends DCacheModule
{
  val io = IO(new DCacheBundle{
11
    val lsu       = Flipped(new DCacheLoadIO)
A
Allen 已提交
12
    val data_read = DecoupledIO(new L1DataReadReq)
A
Allen 已提交
13
    val data_resp = Input(Vec(nWays, Vec(blockRows, Bits(encRowBits.W))))
A
Allen 已提交
14 15
    val meta_read = DecoupledIO(new L1MetaReadReq)
    val meta_resp = Input(Vec(nWays, new L1Metadata))
A
Allen 已提交
16 17 18

    // req got nacked in stage 0?
    val nack      = Input(Bool())
A
Allen 已提交
19 20 21
  })

  // LSU requests
A
Allen 已提交
22 23 24 25 26 27 28 29 30 31 32
  // replayed req should never be nacked
  assert(!(io.lsu.req.valid && io.lsu.req.bits.meta.replay && io.nack))

  // it you got nacked, you can directly passdown
  val not_nacked_ready = io.meta_read.ready && io.data_read.ready
  val nacked_ready     = true.B

  // ready can wait for valid
  io.lsu.req.ready := io.lsu.req.valid && ((!io.nack && not_nacked_ready) || (io.nack && nacked_ready))
  io.meta_read.valid := io.lsu.req.valid && !io.nack
  io.data_read.valid := io.lsu.req.valid && !io.nack
A
Allen 已提交
33 34 35

  val meta_read = io.meta_read.bits
  val data_read = io.data_read.bits
36 37

  // Tag read for new requests
38
  meta_read.idx    := get_idx(io.lsu.req.bits.addr)
39 40 41 42 43
  meta_read.way_en := ~0.U(nWays.W)
  meta_read.tag    := DontCare
  // Data read for new requests
  data_read.addr   := io.lsu.req.bits.addr
  data_read.way_en := ~0.U(nWays.W)
A
Allen 已提交
44 45
  // only needs to read the specific row
  data_read.rmask  := UIntToOH(get_row(io.lsu.req.bits.addr))
A
Allen 已提交
46 47 48 49 50 51 52 53

  // Pipeline
  // stage 0
  val s0_valid = io.lsu.req.fire()
  val s0_req = io.lsu.req.bits

  assert(!(s0_valid && s0_req.cmd =/= MemoryOpConstants.M_XRD), "LoadPipe only accepts load req")

54
  dump_pipeline_reqs("LoadPipe s0", s0_valid, s0_req)
A
Allen 已提交
55 56 57 58

  // stage 1
  val s1_req = RegNext(s0_req)
  val s1_valid = RegNext(s0_valid, init = false.B)
59 60
  // in stage 1, load unit gets the physical address
  val s1_addr = io.lsu.s1_paddr
A
Allen 已提交
61
  val s1_nack = RegNext(io.nack)
A
Allen 已提交
62

63
  dump_pipeline_reqs("LoadPipe s1", s1_valid, s1_req)
A
Allen 已提交
64 65

  // tag check
66
  val meta_resp = io.meta_resp
A
Allen 已提交
67
  def wayMap[T <: Data](f: Int => T) = VecInit((0 until nWays).map(f))
68
  val s1_tag_eq_way = wayMap((w: Int) => meta_resp(w).tag === (get_tag(s1_addr))).asUInt
69
  val s1_tag_match_way = wayMap((w: Int) => s1_tag_eq_way(w) && meta_resp(w).coh.isValid()).asUInt
A
Allen 已提交
70

71
  assert(!(s1_valid && s1_req.meta.replay && io.lsu.s1_kill),
Y
Yinan Xu 已提交
72
    "lsq tried to kill an replayed request!")
A
Allen 已提交
73 74 75

  // stage 2
  val s2_req   = RegNext(s1_req)
76
  val s2_valid = RegNext(s1_valid && !io.lsu.s1_kill, init = false.B)
A
Allen 已提交
77

78
  dump_pipeline_reqs("LoadPipe s2", s2_valid, s2_req)
A
Allen 已提交
79

80
  val s2_addr = RegNext(s1_addr)
A
Allen 已提交
81 82
  val s2_tag_match_way = RegNext(s1_tag_match_way)
  val s2_tag_match     = s2_tag_match_way.orR
83
  val s2_hit_state     = Mux1H(s2_tag_match_way, wayMap((w: Int) => RegNext(meta_resp(w).coh)))
A
Allen 已提交
84 85 86 87 88 89 90 91 92 93 94 95
  val s2_has_permission = s2_hit_state.onAccess(s2_req.cmd)._1
  val s2_new_hit_state  = s2_hit_state.onAccess(s2_req.cmd)._3

  // we not only need permissions
  // we also require that state does not change on hit
  // thus we require new_hit_state === old_hit_state
  //
  // If state changes on hit,
  // we should treat it as not hit, and let mshr deal with it,
  // since we can not write meta data on the main pipeline.
  // It's possible that we had permission but state changes on hit:
  // eg: write to exclusive but clean block
96
  val s2_hit = s2_tag_match && s2_has_permission && s2_hit_state === s2_new_hit_state
A
Allen 已提交
97 98
  val s2_nack = Wire(Bool())
  val s2_data = Wire(Vec(nWays, UInt(encRowBits.W)))
99
  val data_resp = io.data_resp
A
Allen 已提交
100
  for (w <- 0 until nWays) {
101
    s2_data(w) := data_resp(w)(get_row(s2_addr))
A
Allen 已提交
102 103 104 105
  }

  val s2_data_muxed = Mux1H(s2_tag_match_way, s2_data)
  // the index of word in a row, in case rowBits != wordBits
106
  val s2_word_idx   = if (rowWords == 1) 0.U else s2_addr(log2Up(rowWords*wordBytes)-1, log2Up(wordBytes))
A
Allen 已提交
107 108 109 110

  val s2_nack_hit    = RegNext(s1_nack)
  // Can't allocate MSHR for same set currently being written back
  // the same set is busy
111
  val s2_nack_set_busy  = s2_valid && false.B
A
Allen 已提交
112
  // Bank conflict on data arrays
113
  val s2_nack_data   = false.B
A
Allen 已提交
114 115 116

  s2_nack           := s2_nack_hit || s2_nack_set_busy || s2_nack_data

117 118 119 120 121
  // only dump these signals when they are actually valid
  dump_pipeline_valids("LoadPipe s2", "s2_hit", s2_valid && s2_hit)
  dump_pipeline_valids("LoadPipe s2", "s2_nack", s2_valid && s2_nack)
  dump_pipeline_valids("LoadPipe s2", "s2_nack_hit", s2_valid && s2_nack_hit)
  dump_pipeline_valids("LoadPipe s2", "s2_nack_set_busy", s2_valid && s2_nack_set_busy)
A
Allen 已提交
122 123

  // load data gen
A
Allen 已提交
124
  val s2_data_words = Wire(Vec(rowWords, UInt(encWordBits.W)))
A
Allen 已提交
125
  for (w <- 0 until rowWords) {
A
Allen 已提交
126
    s2_data_words(w) := s2_data_muxed(encWordBits * (w + 1) - 1, encWordBits * w)
A
Allen 已提交
127 128 129 130
  }
  val s2_data_word =  s2_data_words(s2_word_idx)
  val s2_decoded = cacheParams.dataCode.decode(s2_data_word)
  val s2_data_word_decoded = s2_decoded.corrected
A
Allen 已提交
131
  assert(!(s2_valid && s2_hit && !s2_nack && s2_decoded.uncorrectable))
A
Allen 已提交
132

A
Allen 已提交
133

134
  val resp = Wire(ValidIO(new DCacheWordResp))
A
Allen 已提交
135
  resp.valid     := s2_valid
A
Allen 已提交
136
  resp.bits.data := s2_data_word_decoded
A
Allen 已提交
137 138 139
  resp.bits.meta := s2_req.meta
  resp.bits.miss := !s2_hit
  resp.bits.nack := s2_nack
A
Allen 已提交
140

A
Allen 已提交
141 142 143
  io.lsu.resp.valid := resp.valid
  io.lsu.resp.bits := resp.bits
  assert(!(resp.valid && !io.lsu.resp.ready))
A
Allen 已提交
144 145

  when (resp.valid) {
146 147
    XSDebug(s"LoadPipe resp: data: %x id: %d replay: %b miss: %b nack: %b\n",
      resp.bits.data, resp.bits.meta.id, resp.bits.meta.replay, resp.bits.miss, resp.bits.nack)
A
Allen 已提交
148 149 150 151
  }

  // -------
  // Debug logging functions
152
  def dump_pipeline_reqs(pipeline_stage_name: String, valid: Bool,
153
    req: DCacheWordReq ) = {
154 155 156
      when (valid) {
        XSDebug(s"$pipeline_stage_name cmd: %x addr: %x data: %x mask: %x id: %d replay: %b\n",
          req.cmd, req.addr, req.data, req.mask, req.meta.id, req.meta.replay)
A
Allen 已提交
157 158 159
      }
  }

160 161 162
  def dump_pipeline_valids(pipeline_stage_name: String, signal_name: String, valid: Bool) = {
    when (valid) {
      XSDebug(s"$pipeline_stage_name $signal_name\n")
A
Allen 已提交
163 164 165
    }
  }
}