xref: /XiangShan/src/main/scala/xiangshan/cache/dcache/mainpipe/AtomicsReplayUnit.scala (revision 026615fc25a5a3481c06c9bd0e7641b054d2e138)
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
43    val block_addr  = Output(Valid(UInt()))
44  })
45
46  val s_invalid :: s_pipe_req :: s_pipe_resp :: s_resp :: Nil = Enum(4)
47  val state = RegInit(s_invalid)
48
49  val req = Reg(new DCacheWordReqWithVaddr)
50
51  // assign default values to output signals
52  io.lsu.req.ready     := state === s_invalid
53  io.lsu.resp.valid    := false.B
54  io.lsu.resp.bits     := DontCare
55
56  io.pipe_req.valid    := false.B
57  io.pipe_req.bits     := DontCare
58
59  io.block_addr.valid := state =/= s_invalid
60  io.block_addr.bits  := req.addr
61
62
63  when (state =/= s_invalid) {
64    XSDebug("AtomicsReplayEntry: state: %d block_addr: %x\n", state, io.block_addr.bits)
65  }
66
67  // --------------------------------------------
68  // s_invalid: receive requests
69  when (state === s_invalid) {
70    when (io.lsu.req.fire()) {
71      req   := io.lsu.req.bits
72      state := s_pipe_req
73    }
74  }
75
76  // --------------------------------------------
77  // replay
78  when (state === s_pipe_req) {
79    io.pipe_req.valid := true.B
80
81    val pipe_req = io.pipe_req.bits
82    pipe_req := DontCare
83    pipe_req.miss := false.B
84    pipe_req.probe := false.B
85    pipe_req.probe_need_data := false.B
86    pipe_req.source := AMO_SOURCE.U
87    pipe_req.cmd    := req.cmd
88    pipe_req.addr   := get_block_addr(req.addr)
89    pipe_req.vaddr  := get_block_addr(req.vaddr)
90    pipe_req.word_idx  := get_word(req.addr)
91    pipe_req.amo_data  := req.data
92    pipe_req.amo_mask  := req.mask
93
94    when (io.pipe_req.fire()) {
95      state := s_pipe_resp
96      assert(!io.pipe_req.bits.vaddr === 0.U)
97    }
98  }
99
100  val resp_data  = Reg(UInt())
101  val resp_id    = Reg(UInt())
102  val resp_error = Reg(Bool())
103  when (state === s_pipe_resp) {
104    // when not miss
105    // everything is OK, simply send response back to sbuffer
106    // when miss and not replay
107    // wait for missQueue to handling miss and replaying our request
108    // when miss and replay
109    // req missed and fail to enter missQueue, manually replay it later
110    // TODO: add assertions:
111    // 1. add a replay delay counter?
112    // 2. when req gets into MissQueue, it should not miss any more
113    when (io.pipe_resp.fire()) {
114      when (io.pipe_resp.bits.miss) {
115        when (io.pipe_resp.bits.replay) {
116          state := s_pipe_req
117        }
118      } .otherwise {
119        resp_data  := io.pipe_resp.bits.data
120        resp_id    := io.pipe_resp.bits.id
121        resp_error := io.pipe_resp.bits.error
122        state := s_resp
123      }
124    }
125  }
126
127  // --------------------------------------------
128  when (state === s_resp) {
129    io.lsu.resp.valid := true.B
130    io.lsu.resp.bits  := DontCare
131    io.lsu.resp.bits.data  := resp_data
132    io.lsu.resp.bits.id    := resp_id
133    io.lsu.resp.bits.error := resp_error
134
135    when (io.lsu.resp.fire()) {
136      state := s_invalid
137    }
138  }
139
140  // debug output
141  when (io.lsu.req.fire()) {
142    io.lsu.req.bits.dump()
143  }
144
145  when (io.lsu.resp.fire()) {
146    io.lsu.resp.bits.dump()
147  }
148
149//  when (io.pipe_req.fire()) {
150//    io.pipe_req.bits.dump()
151//  }
152//
153//  when (io.pipe_resp.fire()) {
154//    io.pipe_resp.bits.dump()
155//  }
156}
157