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