xref: /XiangShan/src/main/scala/xiangshan/cache/dcache/mainpipe/AtomicsReplayUnit.scala (revision 57bb43b5f11c3f1e89ac52f232fe73056b35d9bd)
1/***************************************************************************************
2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3* Copyright (c) 2020-2021 Peng Cheng Laboratory
4*
5* XiangShan is licensed under Mulan PSL v2.
6* You can use this software according to the terms and conditions of the Mulan PSL v2.
7* You may obtain a copy of Mulan PSL v2 at:
8*          http://license.coscl.org.cn/MulanPSL2
9*
10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13*
14* See the Mulan PSL v2 for more details.
15***************************************************************************************/
16
17package xiangshan.cache
18
19import chipsalliance.rocketchip.config.Parameters
20import chisel3._
21import chisel3.util._
22import utils.XSDebug
23
24class AtomicsResp(implicit p: Parameters) extends DCacheBundle {
25  val data    = UInt(DataBits.W)
26  val miss    = Bool()
27  val miss_id = UInt(log2Up(cfg.nMissEntries).W)
28  val replay  = Bool()
29  val error   = Bool()
30
31  val ack_miss_queue = Bool()
32
33  val id     = UInt(reqIdWidth.W)
34}
35
36class AtomicsReplayEntry(implicit p: Parameters) extends DCacheModule
37{
38  val io = IO(new Bundle {
39    val lsu  = Flipped(new DCacheWordIOWithVaddr)
40    val pipe_req  = Decoupled(new MainPipeReq)
41    val pipe_resp = Flipped(ValidIO(new AtomicsResp))
42    val block_lr = Input(Bool())
43
44    val block_addr  = Output(Valid(UInt()))
45  })
46
47  val s_invalid :: s_pipe_req :: s_pipe_resp :: s_resp :: Nil = Enum(4)
48  val state = RegInit(s_invalid)
49
50  val req = Reg(new DCacheWordReqWithVaddr)
51
52  // assign default values to output signals
53  io.lsu.req.ready     := state === s_invalid
54  io.lsu.resp.valid    := false.B
55  io.lsu.resp.bits     := DontCare
56
57  io.pipe_req.valid    := false.B
58  io.pipe_req.bits     := DontCare
59
60  io.block_addr.valid := state =/= s_invalid
61  io.block_addr.bits  := req.addr
62
63
64  when (state =/= s_invalid) {
65    XSDebug("AtomicsReplayEntry: state: %d block_addr: %x\n", state, io.block_addr.bits)
66  }
67
68  // --------------------------------------------
69  // s_invalid: receive requests
70  when (state === s_invalid) {
71    when (io.lsu.req.fire()) {
72      req   := io.lsu.req.bits
73      state := s_pipe_req
74    }
75  }
76
77  // --------------------------------------------
78  // replay
79  when (state === s_pipe_req) {
80    io.pipe_req.valid := Mux(
81      io.pipe_req.bits.cmd === M_XLR,
82      !io.block_lr, // block lr to survive in lr storm
83      true.B
84    )
85
86    val pipe_req = io.pipe_req.bits
87    pipe_req := DontCare
88    pipe_req.miss := false.B
89    pipe_req.probe := false.B
90    pipe_req.probe_need_data := false.B
91    pipe_req.source := AMO_SOURCE.U
92    pipe_req.cmd    := req.cmd
93    pipe_req.addr   := get_block_addr(req.addr)
94    pipe_req.vaddr  := get_block_addr(req.vaddr)
95    pipe_req.word_idx  := get_word(req.addr)
96    pipe_req.amo_data  := req.data
97    pipe_req.amo_mask  := req.mask
98
99    when (io.pipe_req.fire()) {
100      state := s_pipe_resp
101      assert(!io.pipe_req.bits.vaddr === 0.U)
102    }
103  }
104
105  val resp_data  = Reg(UInt())
106  val resp_id    = Reg(UInt())
107  val resp_error = Reg(Bool())
108  when (state === s_pipe_resp) {
109    // when not miss
110    // everything is OK, simply send response back to sbuffer
111    // when miss and not replay
112    // wait for missQueue to handling miss and replaying our request
113    // when miss and replay
114    // req missed and fail to enter missQueue, manually replay it later
115    // TODO: add assertions:
116    // 1. add a replay delay counter?
117    // 2. when req gets into MissQueue, it should not miss any more
118    when (io.pipe_resp.fire()) {
119      when (io.pipe_resp.bits.miss) {
120        when (io.pipe_resp.bits.replay) {
121          state := s_pipe_req
122        }
123      } .otherwise {
124        resp_data  := io.pipe_resp.bits.data
125        resp_id    := io.pipe_resp.bits.id
126        resp_error := io.pipe_resp.bits.error
127        state := s_resp
128      }
129    }
130  }
131
132  // --------------------------------------------
133  when (state === s_resp) {
134    io.lsu.resp.valid := true.B
135    io.lsu.resp.bits  := DontCare
136    io.lsu.resp.bits.data  := resp_data
137    io.lsu.resp.bits.id    := resp_id
138    io.lsu.resp.bits.error := resp_error
139
140    when (io.lsu.resp.fire()) {
141      state := s_invalid
142    }
143  }
144
145  // debug output
146  when (io.lsu.req.fire()) {
147    io.lsu.req.bits.dump()
148  }
149
150  when (io.lsu.resp.fire()) {
151    io.lsu.resp.bits.dump()
152  }
153
154//  when (io.pipe_req.fire()) {
155//    io.pipe_req.bits.dump()
156//  }
157//
158//  when (io.pipe_resp.fire()) {
159//    io.pipe_resp.bits.dump()
160//  }
161}
162