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