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