xref: /XiangShan/src/main/scala/xiangshan/mem/MemCommon.scala (revision 8a00ff566bcba2487c171ffd13c225a25e8ff441)
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.mem
18
19
20import chipsalliance.rocketchip.config.Parameters
21import chisel3._
22import chisel3.util._
23import utility._
24import utils._
25import xiangshan._
26import xiangshan.backend.rob.RobPtr
27import xiangshan.cache._
28import xiangshan.cache.dcache.ReplayCarry
29import xiangshan.backend.Bundles.{DynInst, MemExuInput}
30
31object genWmask {
32  def apply(addr: UInt, sizeEncode: UInt): UInt = {
33    (LookupTree(sizeEncode, List(
34      "b00".U -> 0x1.U, //0001 << addr(2:0)
35      "b01".U -> 0x3.U, //0011
36      "b10".U -> 0xf.U, //1111
37      "b11".U -> 0xff.U //11111111
38    )) << addr(2, 0)).asUInt()
39  }
40}
41
42object genWdata {
43  def apply(data: UInt, sizeEncode: UInt): UInt = {
44    LookupTree(sizeEncode, List(
45      "b00".U -> Fill(8, data(7, 0)),
46      "b01".U -> Fill(4, data(15, 0)),
47      "b10".U -> Fill(2, data(31, 0)),
48      "b11".U -> data
49    ))
50  }
51}
52
53class LsPipelineBundle(implicit val p: Parameters) extends Bundle with HasXSParameter with HasDCacheParameters{
54  val uop = new DynInst
55  val vaddr = UInt(VAddrBits.W)
56  val paddr = UInt(PAddrBits.W)
57  // val func = UInt(6.W)
58  val mask = UInt(8.W)
59  val data = UInt((XLEN+1).W)
60  val wlineflag = Bool() // store write the whole cache line
61
62  val miss = Bool()
63  val tlbMiss = Bool()
64  val ptwBack = Bool()
65  val mmio = Bool()
66  val atomic = Bool()
67  val rsIdx = UInt(log2Up(MemIQSizeMax).W)
68
69  val forwardMask = Vec(8, Bool())
70  val forwardData = Vec(8, UInt(8.W))
71
72  // prefetch
73  val isPrefetch = Bool()
74  val isHWPrefetch = Bool()
75  def isSWPrefetch = isPrefetch && !isHWPrefetch
76
77  // For debug usage
78  val isFirstIssue = Bool()
79
80  // For load replay
81  val isLoadReplay = Bool()
82  val replayCarry = new ReplayCarry
83
84  // For dcache miss load
85  val mshrid = UInt(log2Up(cfg.nMissEntries).W)
86
87  val forward_tlDchannel = Bool()
88}
89
90class LdPrefetchTrainBundle(implicit p: Parameters) extends LsPipelineBundle {
91  val meta_prefetch = Bool()
92  val meta_access = Bool()
93
94  def fromLsPipelineBundle(input: LsPipelineBundle) = {
95    vaddr := input.vaddr
96    paddr := input.paddr
97    mask := input.mask
98    data := input.data
99    uop := input.uop
100    wlineflag := input.wlineflag
101    miss := input.miss
102    tlbMiss := input.tlbMiss
103    ptwBack := input.ptwBack
104    mmio := input.mmio
105    rsIdx := input.rsIdx
106    forwardMask := input.forwardMask
107    forwardData := input.forwardData
108    isPrefetch := input.isPrefetch
109    isHWPrefetch := input.isHWPrefetch
110    isFirstIssue := input.isFirstIssue
111    meta_prefetch := DontCare
112    meta_access := DontCare
113    forward_tlDchannel := DontCare
114    mshrid := DontCare
115    replayCarry := DontCare
116    atomic := DontCare
117    isLoadReplay := DontCare
118  }
119}
120
121class LqWriteBundle(implicit p: Parameters) extends LsPipelineBundle {
122  // queue entry data, except flag bits, will be updated if writeQueue is true,
123  // valid bit in LqWriteBundle will be ignored
124  val lq_data_wen_dup = Vec(6, Bool()) // dirty reg dup
125
126  def fromLsPipelineBundle(input: LsPipelineBundle) = {
127    vaddr := input.vaddr
128    paddr := input.paddr
129    mask := input.mask
130    data := input.data
131    uop := input.uop
132    wlineflag := input.wlineflag
133    miss := input.miss
134    tlbMiss := input.tlbMiss
135    ptwBack := input.ptwBack
136    mmio := input.mmio
137    atomic := input.atomic
138    rsIdx := input.rsIdx
139    forwardMask := input.forwardMask
140    forwardData := input.forwardData
141    isPrefetch := input.isPrefetch
142    isHWPrefetch := input.isHWPrefetch
143    isFirstIssue := input.isFirstIssue
144    isLoadReplay := input.isLoadReplay
145    mshrid := input.mshrid
146    forward_tlDchannel := input.forward_tlDchannel
147    replayCarry := input.replayCarry
148
149    lq_data_wen_dup := DontCare
150  }
151}
152
153class LoadForwardQueryIO(implicit p: Parameters) extends XSBundle {
154  val uop = Output(new DynInst)
155  val vaddr = Output(UInt(VAddrBits.W))
156  val paddr = Output(UInt(PAddrBits.W))
157  val mask = Output(UInt(8.W))
158  val pc = Output(UInt(VAddrBits.W)) //for debug
159  val valid = Output(Bool())
160
161  val forwardMaskFast = Input(Vec(8, Bool())) // resp to load_s1
162  val forwardMask = Input(Vec(8, Bool())) // resp to load_s2
163  val forwardData = Input(Vec(8, UInt(8.W))) // resp to load_s2
164
165  // val lqIdx = Output(UInt(LoadQueueIdxWidth.W))
166  val sqIdx = Output(new SqPtr)
167
168  // dataInvalid suggests store to load forward found forward should happen,
169  // but data is not available for now. If dataInvalid, load inst should
170  // be replayed from RS. Feedback type should be RSFeedbackType.dataInvalid
171  val dataInvalid = Input(Bool()) // Addr match, but data is not valid for now
172
173  // matchInvalid suggests in store to load forward logic, paddr cam result does
174  // to equal to vaddr cam result. If matchInvalid, a microarchitectural exception
175  // should be raised to flush SQ and committed sbuffer.
176  val matchInvalid = Input(Bool()) // resp to load_s2
177}
178
179// LoadForwardQueryIO used in load pipeline
180//
181// Difference between PipeLoadForwardQueryIO and LoadForwardQueryIO:
182// PipeIO use predecoded sqIdxMask for better forward timing
183class PipeLoadForwardQueryIO(implicit p: Parameters) extends LoadForwardQueryIO {
184  // val sqIdx = Output(new SqPtr) // for debug, should not be used in pipeline for timing reasons
185  // sqIdxMask is calcuated in earlier stage for better timing
186  val sqIdxMask = Output(UInt(StoreQueueSize.W))
187
188  // dataInvalid: addr match, but data is not valid for now
189  val dataInvalidFast = Input(Bool()) // resp to load_s1
190  // val dataInvalid = Input(Bool()) // resp to load_s2
191  val dataInvalidSqIdx = Input(UInt(log2Up(StoreQueueSize).W)) // resp to load_s2, sqIdx value
192}
193
194// Query load queue for ld-ld violation
195//
196// Req should be send in load_s1
197// Resp will be generated 1 cycle later
198//
199// Note that query req may be !ready, as dcache is releasing a block
200// If it happens, a replay from rs is needed.
201
202class LoadViolationQueryReq(implicit p: Parameters) extends XSBundle { // provide lqIdx
203  val uop = new DynInst
204  val paddr = UInt(PAddrBits.W)
205}
206
207class LoadViolationQueryResp(implicit p: Parameters) extends XSBundle {
208  val have_violation = Bool()
209}
210
211class LoadViolationQueryIO(implicit p: Parameters) extends XSBundle {
212  val req = Decoupled(new LoadViolationQueryReq)
213  val resp = Flipped(Valid(new LoadViolationQueryResp))
214}
215
216class LoadReExecuteQueryIO(implicit p: Parameters) extends XSBundle {
217  //  robIdx: Requestor's (a store instruction) rob index for match logic.
218  val robIdx = new RobPtr
219
220  //  paddr: requestor's (a store instruction) physical address for match logic.
221  val paddr = UInt(PAddrBits.W)
222
223  //  mask: requestor's (a store instruction) data width mask for match logic.
224  val mask = UInt(8.W)
225}
226
227// Store byte valid mask write bundle
228//
229// Store byte valid mask write to SQ takes 2 cycles
230class StoreMaskBundle(implicit p: Parameters) extends XSBundle {
231  val sqIdx = new SqPtr
232  val mask = UInt(8.W)
233}
234
235class LoadDataFromDcacheBundle(implicit p: Parameters) extends DCacheBundle {
236  // old dcache: optimize data sram read fanout
237  // val bankedDcacheData = Vec(DCacheBanks, UInt(64.W))
238  // val bank_oh = UInt(DCacheBanks.W)
239
240  // new dcache
241  val respDcacheData = UInt(XLEN.W)
242  val forwardMask = Vec(8, Bool())
243  val forwardData = Vec(8, UInt(8.W))
244  val uop = new DynInst // for data selection, only fwen and fuOpType are used
245  val addrOffset = UInt(3.W) // for data selection
246
247  // forward tilelink D channel
248  val forward_D = Input(Bool())
249  val forwardData_D = Input(Vec(8, UInt(8.W)))
250
251  // forward mshr data
252  val forward_mshr = Input(Bool())
253  val forwardData_mshr = Input(Vec(8, UInt(8.W)))
254
255  val forward_result_valid = Input(Bool())
256
257  def dcacheData(): UInt = {
258    // old dcache
259    // val dcache_data = Mux1H(bank_oh, bankedDcacheData)
260    // new dcache
261    val dcache_data = respDcacheData
262    val use_D = forward_D && forward_result_valid
263    val use_mshr = forward_mshr && forward_result_valid
264    Mux(use_D, forwardData_D.asUInt, Mux(use_mshr, forwardData_mshr.asUInt, dcache_data))
265  }
266
267  def mergedData(): UInt = {
268    val rdataVec = VecInit((0 until XLEN / 8).map(j =>
269      Mux(forwardMask(j), forwardData(j), dcacheData()(8*(j+1)-1, 8*j))
270    ))
271    rdataVec.asUInt
272  }
273}
274
275// Load writeback data from load queue (refill)
276class LoadDataFromLQBundle(implicit p: Parameters) extends XSBundle {
277  val lqData = UInt(64.W) // load queue has merged data
278  val uop = new DynInst // for data selection, only fwen and fuOpType are used
279  val addrOffset = UInt(3.W) // for data selection
280
281  def mergedData(): UInt = {
282    lqData
283  }
284}
285
286// Bundle for load / store wait waking up
287class MemWaitUpdateReq(implicit p: Parameters) extends XSBundle {
288  val staIssue = Vec(backendParams.StaCnt, ValidIO(new MemExuInput))
289  val stdIssue = Vec(backendParams.StdCnt, ValidIO(new MemExuInput))
290}
291
292object AddPipelineReg {
293  class PipelineRegModule[T <: Data](gen: T) extends Module {
294    val io = IO(new Bundle() {
295      val in = Flipped(DecoupledIO(gen.cloneType))
296      val out = DecoupledIO(gen.cloneType)
297      val isFlush = Input(Bool())
298    })
299
300    val valid = RegInit(false.B)
301    valid.suggestName("pipeline_reg_valid")
302    when (io.out.fire()) { valid := false.B }
303    when (io.in.fire()) { valid := true.B }
304    when (io.isFlush) { valid := false.B }
305
306    io.in.ready := !valid || io.out.ready
307    io.out.bits := RegEnable(io.in.bits, io.in.fire())
308    io.out.valid := valid //&& !isFlush
309  }
310
311  def apply[T <: Data]
312  (left: DecoupledIO[T], right: DecoupledIO[T], isFlush: Bool,
313   moduleName: Option[String] = None
314  ){
315    val pipelineReg = Module(new PipelineRegModule[T](left.bits.cloneType))
316    if(moduleName.nonEmpty) pipelineReg.suggestName(moduleName.get)
317    pipelineReg.io.in <> left
318    right <> pipelineReg.io.out
319    pipelineReg.io.isFlush := isFlush
320  }
321}
322