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 org.chipsalliance.cde.config.Parameters 21import chisel3._ 22import chisel3.util._ 23import utility._ 24import utils._ 25import xiangshan._ 26import xiangshan.backend.Bundles.{DynInst, MemExuInput} 27import xiangshan.backend.rob.RobPtr 28import xiangshan.cache._ 29import xiangshan.backend.fu.FenceToSbuffer 30import xiangshan.cache.wpu.ReplayCarry 31import xiangshan.mem.prefetch.PrefetchReqBundle 32 33object genWmask { 34 def apply(addr: UInt, sizeEncode: UInt): UInt = { 35 (LookupTree(sizeEncode, List( 36 "b00".U -> 0x1.U, //0001 << addr(2:0) 37 "b01".U -> 0x3.U, //0011 38 "b10".U -> 0xf.U, //1111 39 "b11".U -> 0xff.U //11111111 40 )) << addr(2, 0)).asUInt 41 } 42} 43 44object genVWmask { 45 def apply(addr: UInt, sizeEncode: UInt): UInt = { 46 (LookupTree(sizeEncode, List( 47 "b00".U -> 0x1.U, //0001 << addr(2:0) 48 "b01".U -> 0x3.U, //0011 49 "b10".U -> 0xf.U, //1111 50 "b11".U -> 0xff.U //11111111 51 )) << addr(3, 0)).asUInt 52 } 53} 54 55object genWdata { 56 def apply(data: UInt, sizeEncode: UInt): UInt = { 57 LookupTree(sizeEncode, List( 58 "b00".U -> Fill(16, data(7, 0)), 59 "b01".U -> Fill(8, data(15, 0)), 60 "b10".U -> Fill(4, data(31, 0)), 61 "b11".U -> Fill(2, data(63,0)) 62 )) 63 } 64} 65 66object shiftDataToLow { 67 def apply(addr: UInt,data : UInt): UInt = { 68 Mux(addr(3), (data >> 64).asUInt,data) 69 } 70} 71object shiftMaskToLow { 72 def apply(addr: UInt,mask: UInt): UInt = { 73 Mux(addr(3),(mask >> 8).asUInt,mask) 74 } 75} 76 77class LsPipelineBundle(implicit p: Parameters) extends XSBundle with HasDCacheParameters{ 78 val uop = new DynInst 79 val vaddr = UInt(VAddrBits.W) 80 val paddr = UInt(PAddrBits.W) 81 // val func = UInt(6.W) 82 val mask = UInt((VLEN/8).W) 83 val data = UInt((VLEN+1).W) 84 val wlineflag = Bool() // store write the whole cache line 85 86 val miss = Bool() 87 val tlbMiss = Bool() 88 val ptwBack = Bool() 89 val mmio = Bool() 90 val atomic = Bool() 91 val rsIdx = UInt(log2Up(MemIQSizeMax).W) 92 93 val forwardMask = Vec(VLEN/8, Bool()) 94 val forwardData = Vec(VLEN/8, UInt(8.W)) 95 96 // prefetch 97 val isPrefetch = Bool() 98 val isHWPrefetch = Bool() 99 def isSWPrefetch = isPrefetch && !isHWPrefetch 100 101 // For debug usage 102 val isFirstIssue = Bool() 103 val hasROBEntry = Bool() 104 105 // For load replay 106 val isLoadReplay = Bool() 107 val isFastPath = Bool() 108 val isFastReplay = Bool() 109 val replayCarry = new ReplayCarry(nWays) 110 111 // For dcache miss load 112 val mshrid = UInt(log2Up(cfg.nMissEntries).W) 113 val handledByMSHR = Bool() 114 val replacementUpdated = Bool() 115 val missDbUpdated = Bool() 116 117 val forward_tlDchannel = Bool() 118 val dcacheRequireReplay = Bool() 119 val delayedLoadError = Bool() 120 val lateKill = Bool() 121 val feedbacked = Bool() 122 val ldCancel = ValidUndirectioned(UInt(log2Ceil(LoadPipelineWidth).W)) 123 // loadQueueReplay index. 124 val schedIndex = UInt(log2Up(LoadQueueReplaySize).W) 125 126 // issue dequeue port index 127 val deqPortIdx = UInt(log2Ceil(LoadPipelineWidth).W) 128} 129 130class LdPrefetchTrainBundle(implicit p: Parameters) extends LsPipelineBundle { 131 val meta_prefetch = UInt(L1PfSourceBits.W) 132 val meta_access = Bool() 133 134 def fromLsPipelineBundle(input: LsPipelineBundle) = { 135 vaddr := input.vaddr 136 paddr := input.paddr 137 mask := input.mask 138 data := input.data 139 uop := input.uop 140 wlineflag := input.wlineflag 141 miss := input.miss 142 tlbMiss := input.tlbMiss 143 ptwBack := input.ptwBack 144 mmio := input.mmio 145 rsIdx := input.rsIdx 146 forwardMask := input.forwardMask 147 forwardData := input.forwardData 148 isPrefetch := input.isPrefetch 149 isHWPrefetch := input.isHWPrefetch 150 isFirstIssue := input.isFirstIssue 151 hasROBEntry := input.hasROBEntry 152 dcacheRequireReplay := input.dcacheRequireReplay 153 schedIndex := input.schedIndex 154 155 meta_prefetch := DontCare 156 meta_access := DontCare 157 forward_tlDchannel := DontCare 158 mshrid := DontCare 159 replayCarry := DontCare 160 atomic := DontCare 161 isLoadReplay := DontCare 162 isFastPath := DontCare 163 isFastReplay := DontCare 164 handledByMSHR := DontCare 165 replacementUpdated := DontCare 166 missDbUpdated := DontCare 167 delayedLoadError := DontCare 168 lateKill := DontCare 169 feedbacked := DontCare 170 deqPortIdx := DontCare 171 ldCancel := DontCare 172 } 173 174 def asPrefetchReqBundle(): PrefetchReqBundle = { 175 val res = Wire(new PrefetchReqBundle) 176 res.vaddr := this.vaddr 177 res.paddr := this.paddr 178 res.pc := this.uop.pc 179 180 res 181 } 182} 183 184class StPrefetchTrainBundle(implicit p: Parameters) extends LdPrefetchTrainBundle {} 185 186class LqWriteBundle(implicit p: Parameters) extends LsPipelineBundle { 187 // load inst replay informations 188 val rep_info = new LoadToLsqReplayIO 189 // queue entry data, except flag bits, will be updated if writeQueue is true, 190 // valid bit in LqWriteBundle will be ignored 191 val data_wen_dup = Vec(6, Bool()) // dirty reg dup 192 193 194 def fromLsPipelineBundle(input: LsPipelineBundle) = { 195 vaddr := input.vaddr 196 paddr := input.paddr 197 mask := input.mask 198 data := input.data 199 uop := input.uop 200 wlineflag := input.wlineflag 201 miss := input.miss 202 tlbMiss := input.tlbMiss 203 ptwBack := input.ptwBack 204 mmio := input.mmio 205 atomic := input.atomic 206 rsIdx := input.rsIdx 207 forwardMask := input.forwardMask 208 forwardData := input.forwardData 209 isPrefetch := input.isPrefetch 210 isHWPrefetch := input.isHWPrefetch 211 isFirstIssue := input.isFirstIssue 212 hasROBEntry := input.hasROBEntry 213 isLoadReplay := input.isLoadReplay 214 isFastPath := input.isFastPath 215 isFastReplay := input.isFastReplay 216 mshrid := input.mshrid 217 forward_tlDchannel := input.forward_tlDchannel 218 replayCarry := input.replayCarry 219 dcacheRequireReplay := input.dcacheRequireReplay 220 schedIndex := input.schedIndex 221 handledByMSHR := input.handledByMSHR 222 replacementUpdated := input.replacementUpdated 223 missDbUpdated := input.missDbUpdated 224 delayedLoadError := input.delayedLoadError 225 lateKill := input.lateKill 226 feedbacked := input.feedbacked 227 228 rep_info := DontCare 229 data_wen_dup := DontCare 230 } 231} 232 233class LoadForwardQueryIO(implicit p: Parameters) extends XSBundle { 234 val vaddr = Output(UInt(VAddrBits.W)) 235 val paddr = Output(UInt(PAddrBits.W)) 236 val mask = Output(UInt((VLEN/8).W)) 237 val uop = Output(new DynInst) // for replay 238 val pc = Output(UInt(VAddrBits.W)) //for debug 239 val valid = Output(Bool()) 240 241 val forwardMaskFast = Input(Vec((VLEN/8), Bool())) // resp to load_s1 242 val forwardMask = Input(Vec((VLEN/8), Bool())) // resp to load_s2 243 val forwardData = Input(Vec((VLEN/8), UInt(8.W))) // resp to load_s2 244 245 // val lqIdx = Output(UInt(LoadQueueIdxWidth.W)) 246 val sqIdx = Output(new SqPtr) 247 248 // dataInvalid suggests store to load forward found forward should happen, 249 // but data is not available for now. If dataInvalid, load inst should 250 // be replayed from RS. Feedback type should be RSFeedbackType.dataInvalid 251 val dataInvalid = Input(Bool()) // Addr match, but data is not valid for now 252 253 // matchInvalid suggests in store to load forward logic, paddr cam result does 254 // to equal to vaddr cam result. If matchInvalid, a microarchitectural exception 255 // should be raised to flush SQ and committed sbuffer. 256 val matchInvalid = Input(Bool()) // resp to load_s2 257 258 // addrInvalid suggests store to load forward found forward should happen, 259 // but address (SSID) is not available for now. If addrInvalid, load inst should 260 // be replayed from RS. Feedback type should be RSFeedbackType.addrInvalid 261 val addrInvalid = Input(Bool()) 262} 263 264// LoadForwardQueryIO used in load pipeline 265// 266// Difference between PipeLoadForwardQueryIO and LoadForwardQueryIO: 267// PipeIO use predecoded sqIdxMask for better forward timing 268class PipeLoadForwardQueryIO(implicit p: Parameters) extends LoadForwardQueryIO { 269 // val sqIdx = Output(new SqPtr) // for debug, should not be used in pipeline for timing reasons 270 // sqIdxMask is calcuated in earlier stage for better timing 271 val sqIdxMask = Output(UInt(StoreQueueSize.W)) 272 273 // dataInvalid: addr match, but data is not valid for now 274 val dataInvalidFast = Input(Bool()) // resp to load_s1 275 // val dataInvalid = Input(Bool()) // resp to load_s2 276 val dataInvalidSqIdx = Input(new SqPtr) // resp to load_s2, sqIdx 277 val addrInvalidSqIdx = Input(new SqPtr) // resp to load_s2, sqIdx 278} 279 280// Query load queue for ld-ld violation 281// 282// Req should be send in load_s1 283// Resp will be generated 1 cycle later 284// 285// Note that query req may be !ready, as dcache is releasing a block 286// If it happens, a replay from rs is needed. 287class LoadNukeQueryReq(implicit p: Parameters) extends XSBundle { // provide lqIdx 288 val uop = new DynInst 289 // mask: load's data mask. 290 val mask = UInt((VLEN/8).W) 291 292 // paddr: load's paddr. 293 val paddr = UInt(PAddrBits.W) 294 // dataInvalid: load data is invalid. 295 val data_valid = Bool() 296} 297 298class LoadNukeQueryResp(implicit p: Parameters) extends XSBundle { 299 // rep_frm_fetch: ld-ld violation check success, replay from fetch. 300 val rep_frm_fetch = Bool() 301} 302 303class LoadNukeQueryIO(implicit p: Parameters) extends XSBundle { 304 val req = Decoupled(new LoadNukeQueryReq) 305 val resp = Flipped(Valid(new LoadNukeQueryResp)) 306 val revoke = Output(Bool()) 307} 308 309class StoreNukeQueryIO(implicit p: Parameters) extends XSBundle { 310 // robIdx: Requestor's (a store instruction) rob index for match logic. 311 val robIdx = new RobPtr 312 313 // paddr: requestor's (a store instruction) physical address for match logic. 314 val paddr = UInt(PAddrBits.W) 315 316 // mask: requestor's (a store instruction) data width mask for match logic. 317 val mask = UInt((VLEN/8).W) 318} 319 320// Store byte valid mask write bundle 321// 322// Store byte valid mask write to SQ takes 2 cycles 323class StoreMaskBundle(implicit p: Parameters) extends XSBundle { 324 val sqIdx = new SqPtr 325 val mask = UInt((VLEN/8).W) 326} 327 328class LoadDataFromDcacheBundle(implicit p: Parameters) extends DCacheBundle { 329 // old dcache: optimize data sram read fanout 330 // val bankedDcacheData = Vec(DCacheBanks, UInt(64.W)) 331 // val bank_oh = UInt(DCacheBanks.W) 332 333 // new dcache 334 val respDcacheData = UInt(VLEN.W) 335 val forwardMask = Vec(VLEN/8, Bool()) 336 val forwardData = Vec(VLEN/8, UInt(8.W)) 337 val uop = new DynInst // for data selection, only fwen and fuOpType are used 338 val addrOffset = UInt(4.W) // for data selection 339 // forward tilelink D channel 340 val forward_D = Bool() 341 val forwardData_D = Vec(VLEN/8, UInt(8.W)) 342 343 // forward mshr data 344 val forward_mshr = Bool() 345 val forwardData_mshr = Vec(VLEN/8, UInt(8.W)) 346 347 val forward_result_valid = Bool() 348 349 def dcacheData(): UInt = { 350 // old dcache 351 // val dcache_data = Mux1H(bank_oh, bankedDcacheData) 352 // new dcache 353 val dcache_data = respDcacheData 354 val use_D = forward_D && forward_result_valid 355 val use_mshr = forward_mshr && forward_result_valid 356 Mux(use_D, forwardData_D.asUInt, Mux(use_mshr, forwardData_mshr.asUInt, dcache_data)) 357 } 358 359 def mergedData(): UInt = { 360 val rdataVec = VecInit((0 until VLEN / 8).map(j => 361 Mux(forwardMask(j), forwardData(j), dcacheData()(8*(j+1)-1, 8*j)) 362 )) 363 rdataVec.asUInt 364 } 365} 366 367// Load writeback data from load queue (refill) 368class LoadDataFromLQBundle(implicit p: Parameters) extends XSBundle { 369 val lqData = UInt(64.W) // load queue has merged data 370 val uop = new DynInst // for data selection, only fwen and fuOpType are used 371 val addrOffset = UInt(3.W) // for data selection 372 373 def mergedData(): UInt = { 374 lqData 375 } 376} 377 378// Bundle for load / store wait waking up 379class MemWaitUpdateReq(implicit p: Parameters) extends XSBundle { 380 val robIdx = Vec(backendParams.StaCnt, ValidIO(new RobPtr)) 381 val sqIdx = Vec(backendParams.StdCnt, ValidIO(new SqPtr)) 382} 383 384object AddPipelineReg { 385 class PipelineRegModule[T <: Data](gen: T) extends Module { 386 val io = IO(new Bundle() { 387 val in = Flipped(DecoupledIO(gen.cloneType)) 388 val out = DecoupledIO(gen.cloneType) 389 val isFlush = Input(Bool()) 390 }) 391 392 val valid = RegInit(false.B) 393 valid.suggestName("pipeline_reg_valid") 394 when (io.out.fire) { valid := false.B } 395 when (io.in.fire) { valid := true.B } 396 when (io.isFlush) { valid := false.B } 397 398 io.in.ready := !valid || io.out.ready 399 io.out.bits := RegEnable(io.in.bits, io.in.fire) 400 io.out.valid := valid //&& !isFlush 401 } 402 403 def apply[T <: Data] 404 (left: DecoupledIO[T], right: DecoupledIO[T], isFlush: Bool, 405 moduleName: Option[String] = None 406 ){ 407 val pipelineReg = Module(new PipelineRegModule[T](left.bits.cloneType)) 408 if(moduleName.nonEmpty) pipelineReg.suggestName(moduleName.get) 409 pipelineReg.io.in <> left 410 right <> pipelineReg.io.out 411 pipelineReg.io.isFlush := isFlush 412 } 413} 414