ldu.scala 5.8 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 DCacheWordIO)
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 59

  // stage 1
  val s1_req = RegNext(s0_req)
  val s1_valid = RegNext(s0_valid, init = false.B)
  val s1_addr = s1_req.addr
A
Allen 已提交
60
  val s1_nack = RegNext(io.nack)
A
Allen 已提交
61

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

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

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

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

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

  val s2_tag_match_way = RegNext(s1_tag_match_way)
  val s2_tag_match     = s2_tag_match_way.orR
81
  val s2_hit_state     = Mux1H(s2_tag_match_way, wayMap((w: Int) => RegNext(meta_resp(w).coh)))
A
Allen 已提交
82 83 84 85 86 87 88 89 90 91 92 93
  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
94
  val s2_hit = s2_tag_match && s2_has_permission && s2_hit_state === s2_new_hit_state
A
Allen 已提交
95 96
  val s2_nack = Wire(Bool())
  val s2_data = Wire(Vec(nWays, UInt(encRowBits.W)))
97
  val data_resp = io.data_resp
A
Allen 已提交
98
  for (w <- 0 until nWays) {
A
Allen 已提交
99
    s2_data(w) := data_resp(w)(get_row(s2_req.addr))
A
Allen 已提交
100 101 102 103 104 105 106 107 108
  }

  val s2_data_muxed = Mux1H(s2_tag_match_way, s2_data)
  // the index of word in a row, in case rowBits != wordBits
  val s2_word_idx   = if (rowWords == 1) 0.U else s2_req.addr(log2Up(rowWords*wordBytes)-1, log2Up(wordBytes))

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

  s2_nack           := s2_nack_hit || s2_nack_set_busy || s2_nack_data

115 116 117 118 119
  // 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 已提交
120 121

  // load data gen
A
Allen 已提交
122
  val s2_data_words = Wire(Vec(rowWords, UInt(encWordBits.W)))
A
Allen 已提交
123
  for (w <- 0 until rowWords) {
A
Allen 已提交
124
    s2_data_words(w) := s2_data_muxed(encWordBits * (w + 1) - 1, encWordBits * w)
A
Allen 已提交
125 126 127 128
  }
  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 已提交
129
  assert(!(s2_valid && s2_hit && !s2_nack && s2_decoded.uncorrectable))
A
Allen 已提交
130

A
Allen 已提交
131

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

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

  when (resp.valid) {
144 145
    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 已提交
146 147 148 149
  }

  // -------
  // Debug logging functions
150
  def dump_pipeline_reqs(pipeline_stage_name: String, valid: Bool,
151
    req: DCacheWordReq ) = {
152 153 154
      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 已提交
155 156 157
      }
  }

158 159 160
  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 已提交
161 162 163
    }
  }
}