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