1/*************************************************************************************** 2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3* 4* XiangShan is licensed under Mulan PSL v2. 5* You can use this software according to the terms and conditions of the Mulan PSL v2. 6* You may obtain a copy of Mulan PSL v2 at: 7* http://license.coscl.org.cn/MulanPSL2 8* 9* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 10* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 11* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 12* 13* See the Mulan PSL v2 for more details. 14***************************************************************************************/ 15 16package xiangshan.mem 17 18import chipsalliance.rocketchip.config.Parameters 19import chisel3._ 20import chisel3.util._ 21import utils._ 22import xiangshan._ 23import xiangshan.cache._ 24import xiangshan.cache.{DCacheWordIO, DCacheLineIO, TlbRequestIO, MemoryOpConstants} 25import xiangshan.mem._ 26import xiangshan.backend.roq.RoqPtr 27 28class LQDataEntry(implicit p: Parameters) extends XSBundle { 29 // val vaddr = UInt(VAddrBits.W) 30 val paddr = UInt(PAddrBits.W) 31 val mask = UInt(8.W) 32 val data = UInt(XLEN.W) 33 val fwdMask = Vec(8, Bool()) 34} 35 36// Data module define 37// These data modules are like SyncDataModuleTemplate, but support cam-like ops 38class LQPaddrModule(numEntries: Int, numRead: Int, numWrite: Int)(implicit p: Parameters) extends XSModule with HasDCacheParameters { 39 val io = IO(new Bundle { 40 val raddr = Input(Vec(numRead, UInt(log2Up(numEntries).W))) 41 val rdata = Output(Vec(numRead, UInt((PAddrBits).W))) 42 val wen = Input(Vec(numWrite, Bool())) 43 val waddr = Input(Vec(numWrite, UInt(log2Up(numEntries).W))) 44 val wdata = Input(Vec(numWrite, UInt((PAddrBits).W))) 45 val violationMdata = Input(Vec(2, UInt((PAddrBits).W))) 46 val violationMmask = Output(Vec(2, Vec(numEntries, Bool()))) 47 val refillMdata = Input(UInt((PAddrBits).W)) 48 val refillMmask = Output(Vec(numEntries, Bool())) 49 }) 50 51 val data = Reg(Vec(numEntries, UInt((PAddrBits).W))) 52 53 // read ports 54 for (i <- 0 until numRead) { 55 io.rdata(i) := data(RegNext(io.raddr(i))) 56 } 57 58 // below is the write ports (with priorities) 59 for (i <- 0 until numWrite) { 60 when (io.wen(i)) { 61 data(io.waddr(i)) := io.wdata(i) 62 } 63 } 64 65 // content addressed match 66 for (i <- 0 until 2) { 67 for (j <- 0 until numEntries) { 68 io.violationMmask(i)(j) := io.violationMdata(i)(PAddrBits-1, 3) === data(j)(PAddrBits-1, 3) 69 } 70 } 71 72 for (j <- 0 until numEntries) { 73 io.refillMmask(j) := get_block_addr(io.refillMdata) === get_block_addr(data(j)) 74 } 75 76 // DataModuleTemplate should not be used when there're any write conflicts 77 for (i <- 0 until numWrite) { 78 for (j <- i+1 until numWrite) { 79 assert(!(io.wen(i) && io.wen(j) && io.waddr(i) === io.waddr(j))) 80 } 81 } 82} 83 84class MaskModule(numEntries: Int, numRead: Int, numWrite: Int)(implicit p: Parameters) extends XSModule { 85 val io = IO(new Bundle { 86 val raddr = Input(Vec(numRead, UInt(log2Up(numEntries).W))) 87 val rdata = Output(Vec(numRead, UInt(8.W))) 88 val wen = Input(Vec(numWrite, Bool())) 89 val waddr = Input(Vec(numWrite, UInt(log2Up(numEntries).W))) 90 val wdata = Input(Vec(numWrite, UInt(8.W))) 91 val violationMdata = Input(Vec(2, UInt((PAddrBits).W))) 92 val violationMmask = Output(Vec(2, Vec(numEntries, Bool()))) 93 }) 94 95 val data = Reg(Vec(numEntries, UInt(8.W))) 96 97 // read ports 98 for (i <- 0 until numRead) { 99 io.rdata(i) := data(RegNext(io.raddr(i))) 100 } 101 102 // below is the write ports (with priorities) 103 for (i <- 0 until numWrite) { 104 when (io.wen(i)) { 105 data(io.waddr(i)) := io.wdata(i) 106 } 107 } 108 109 // content addressed match 110 for (i <- 0 until 2) { 111 for (j <- 0 until numEntries) { 112 io.violationMmask(i)(j) := (io.violationMdata(i) & data(j)).orR 113 } 114 } 115 116 // DataModuleTemplate should not be used when there're any write conflicts 117 for (i <- 0 until numWrite) { 118 for (j <- i+1 until numWrite) { 119 assert(!(io.wen(i) && io.wen(j) && io.waddr(i) === io.waddr(j))) 120 } 121 } 122} 123 124// class LQData8Module(numEntries: Int, numRead: Int, numWrite: Int) extends XSModule with HasDCacheParameters { 125// val io = IO(new Bundle { 126// // read 127// val raddr = Input(Vec(numRead, UInt(log2Up(numEntries).W))) 128// val rdata = Output(Vec(numRead, UInt(8.W))) 129// // address indexed write 130// val wen = Input(Vec(numWrite, Bool())) 131// val waddr = Input(Vec(numWrite, UInt(log2Up(numEntries).W))) 132// val wdata = Input(Vec(numWrite, UInt(8.W))) 133// // masked write 134// val mwmask = Input(Vec(blockWords, Vec(numEntries, Bool()))) 135// val mwdata = Input(Vec(blockWords, UInt(8.W))) 136// }) 137 138// val data = Reg(Vec(numEntries, UInt(8.W))) 139 140// // read ports 141// for (i <- 0 until numRead) { 142// io.rdata(i) := data(RegNext(io.raddr(i))) 143// } 144 145// // below is the write ports (with priorities) 146// for (i <- 0 until numWrite) { 147// when (io.wen(i)) { 148// data(io.waddr(i)) := io.wdata(i) 149// } 150// } 151 152// // masked write 153// for (j <- 0 until numEntries) { 154// val wen = VecInit((0 until blockWords).map(i => io.mwmask(i)(j))).asUInt.orR 155// when (wen) { 156// data(j) := VecInit((0 until blockWords).map(i => { 157// Mux(io.mwmask(i)(j), io.mwdata(i), 0.U) 158// })).reduce(_ | _) 159// } 160// } 161 162// // DataModuleTemplate should not be used when there're any write conflicts 163// for (i <- 0 until numWrite) { 164// for (j <- i+1 until numWrite) { 165// assert(!(io.wen(i) && io.wen(j) && io.waddr(i) === io.waddr(j))) 166// } 167// } 168// } 169 170class CoredataModule(numEntries: Int, numRead: Int, numWrite: Int)(implicit p: Parameters) extends XSModule with HasDCacheParameters { 171 val io = IO(new Bundle { 172 // data io 173 // read 174 val raddr = Input(Vec(numRead, UInt(log2Up(numEntries).W))) 175 val rdata = Output(Vec(numRead, UInt(XLEN.W))) 176 // address indexed write 177 val wen = Input(Vec(numWrite, Bool())) 178 val waddr = Input(Vec(numWrite, UInt(log2Up(numEntries).W))) 179 val wdata = Input(Vec(numWrite, UInt(XLEN.W))) 180 // masked write 181 val mwmask = Input(Vec(numEntries, Bool())) 182 val refillData = Input(UInt((cfg.blockBytes * 8).W)) 183 184 // fwdMask io 185 val fwdMaskWdata = Input(Vec(numWrite, UInt(8.W))) 186 val fwdMaskWen = Input(Vec(numWrite, Bool())) 187 // fwdMaskWaddr = waddr 188 189 // paddr io 190 // 3 bits in paddr need to be stored in CoredataModule for refilling 191 val paddrWdata = Input(Vec(numWrite, UInt((PAddrBits).W))) 192 val paddrWen = Input(Vec(numWrite, Bool())) 193 }) 194 195 val data8 = Seq.fill(8)(Module(new MaskedSyncDataModuleTemplate(UInt(8.W), numEntries, numRead, numWrite, numMWrite = blockWords))) 196 val fwdMask = Reg(Vec(numEntries, UInt(8.W))) 197 val wordIndex = Reg(Vec(numEntries, UInt((blockOffBits - wordOffBits).W))) 198 199 // read ports 200 for (i <- 0 until numRead) { 201 for (j <- 0 until 8) { 202 data8(j).io.raddr(i) := io.raddr(i) 203 } 204 io.rdata(i) := VecInit((0 until 8).map(j => data8(j).io.rdata(i))).asUInt 205 } 206 207 // below is the write ports (with priorities) 208 for (i <- 0 until numWrite) { 209 // write to data8 210 for (j <- 0 until 8) { 211 data8(j).io.waddr(i) := io.waddr(i) 212 data8(j).io.wdata(i) := io.wdata(i)(8*(j+1)-1, 8*j) 213 data8(j).io.wen(i) := io.wen(i) 214 } 215 216 // write ctrl info 217 when (io.fwdMaskWen(i)) { 218 fwdMask(io.waddr(i)) := io.fwdMaskWdata(i) 219 } 220 when (io.paddrWen(i)) { 221 wordIndex(io.waddr(i)) := get_word(io.paddrWdata(i)) 222 } 223 } 224 225 // write refilled data to data8 226 227 // select refill data 228 // split dcache result into words 229 val words = VecInit((0 until blockWords) map { i => io.refillData(DataBits * (i + 1) - 1, DataBits * i)}) 230 // select refill data according to wordIndex (paddr) 231 for (i <- 0 until 8) { 232 for (j <- 0 until blockWords) { 233 data8(i).io.mwdata(j) := words(j)(8*(i+1)-1, 8*i) 234 } 235 } 236 237 // gen refill wmask 238 for (j <- 0 until blockWords) { 239 for (k <- 0 until numEntries) { 240 val wordMatch = wordIndex(k) === j.U 241 for (i <- 0 until 8) { 242 data8(i).io.mwmask(j)(k) := wordMatch && io.mwmask(k) && !fwdMask(k)(i) 243 } 244 } 245 } 246 247 // DataModuleTemplate should not be used when there're any write conflicts 248 for (i <- 0 until numWrite) { 249 for (j <- i+1 until numWrite) { 250 assert(!(io.wen(i) && io.wen(j) && io.waddr(i) === io.waddr(j))) 251 } 252 } 253} 254 255class LoadQueueData(size: Int, wbNumRead: Int, wbNumWrite: Int)(implicit p: Parameters) extends XSModule with HasDCacheParameters with HasCircularQueuePtrHelper { 256 val io = IO(new Bundle() { 257 val wb = new Bundle() { 258 val wen = Vec(wbNumWrite, Input(Bool())) 259 val waddr = Input(Vec(wbNumWrite, UInt(log2Up(size).W))) 260 val wdata = Input(Vec(wbNumWrite, new LQDataEntry)) 261 val raddr = Input(Vec(wbNumRead, UInt(log2Up(size).W))) 262 val rdata = Output(Vec(wbNumRead, new LQDataEntry)) 263 } 264 val uncache = new Bundle() { 265 val wen = Input(Bool()) 266 val waddr = Input(UInt(log2Up(size).W)) 267 val wdata = Input(UInt(XLEN.W)) // only write back uncache data 268 val raddr = Input(UInt(log2Up(size).W)) 269 val rdata = Output(new LQDataEntry) 270 } 271 val refill = new Bundle() { 272 val valid = Input(Bool()) 273 val paddr = Input(UInt(PAddrBits.W)) 274 val data = Input(UInt((cfg.blockBytes * 8).W)) 275 val refillMask = Input(Vec(size, Bool())) 276 val matchMask = Output(Vec(size, Bool())) 277 } 278 val violation = Vec(StorePipelineWidth, new Bundle() { 279 val paddr = Input(UInt(PAddrBits.W)) 280 val mask = Input(UInt(8.W)) 281 val violationMask = Output(Vec(size, Bool())) 282 }) 283 val debug = Output(Vec(size, new LQDataEntry)) 284 285 def wbWrite(channel: Int, waddr: UInt, wdata: LQDataEntry): Unit = { 286 require(channel < wbNumWrite && wbNumWrite >= 0) 287 // need extra "this.wb(channel).wen := true.B" 288 this.wb.waddr(channel) := waddr 289 this.wb.wdata(channel) := wdata 290 } 291 292 def uncacheWrite(waddr: UInt, wdata: UInt): Unit = { 293 // need extra "this.uncache.wen := true.B" 294 this.uncache.waddr := waddr 295 this.uncache.wdata := wdata 296 } 297 298 // def refillWrite(ldIdx: Int): Unit = { 299 // } 300 // use "this.refill.wen(ldIdx) := true.B" instead 301 }) 302 303 // val data = Reg(Vec(size, new LQDataEntry)) 304 // data module 305 val paddrModule = Module(new LQPaddrModule(size, numRead = 3, numWrite = 2)) 306 val maskModule = Module(new MaskModule(size, numRead = 3, numWrite = 2)) 307 val coredataModule = Module(new CoredataModule(size, numRead = 3, numWrite = 3)) 308 309 // read data 310 // read port 0 -> wbNumRead-1 311 (0 until wbNumRead).map(i => { 312 paddrModule.io.raddr(i) := io.wb.raddr(i) 313 maskModule.io.raddr(i) := io.wb.raddr(i) 314 coredataModule.io.raddr(i) := io.wb.raddr(i) 315 316 io.wb.rdata(i).paddr := paddrModule.io.rdata(i) 317 io.wb.rdata(i).mask := maskModule.io.rdata(i) 318 io.wb.rdata(i).data := coredataModule.io.rdata(i) 319 io.wb.rdata(i).fwdMask := DontCare 320 }) 321 322 // read port wbNumRead 323 paddrModule.io.raddr(wbNumRead) := io.uncache.raddr 324 maskModule.io.raddr(wbNumRead) := io.uncache.raddr 325 coredataModule.io.raddr(wbNumRead) := io.uncache.raddr 326 327 io.uncache.rdata.paddr := paddrModule.io.rdata(wbNumRead) 328 io.uncache.rdata.mask := maskModule.io.rdata(wbNumRead) 329 io.uncache.rdata.data := coredataModule.io.rdata(wbNumRead) 330 io.uncache.rdata.fwdMask := DontCare 331 332 // write data 333 // write port 0 -> wbNumWrite-1 334 (0 until wbNumWrite).map(i => { 335 paddrModule.io.wen(i) := false.B 336 maskModule.io.wen(i) := false.B 337 coredataModule.io.wen(i) := false.B 338 coredataModule.io.fwdMaskWen(i) := false.B 339 coredataModule.io.paddrWen(i) := false.B 340 341 paddrModule.io.waddr(i) := io.wb.waddr(i) 342 maskModule.io.waddr(i) := io.wb.waddr(i) 343 coredataModule.io.waddr(i) := io.wb.waddr(i) 344 345 paddrModule.io.wdata(i) := io.wb.wdata(i).paddr 346 maskModule.io.wdata(i) := io.wb.wdata(i).mask 347 coredataModule.io.wdata(i) := io.wb.wdata(i).data 348 coredataModule.io.fwdMaskWdata(i) := io.wb.wdata(i).fwdMask.asUInt 349 coredataModule.io.paddrWdata(i) := io.wb.wdata(i).paddr 350 351 when(io.wb.wen(i)){ 352 paddrModule.io.wen(i) := true.B 353 maskModule.io.wen(i) := true.B 354 coredataModule.io.wen(i) := true.B 355 coredataModule.io.fwdMaskWen(i) := true.B 356 coredataModule.io.paddrWen(i) := true.B 357 } 358 }) 359 360 // write port wbNumWrite 361 // exceptionModule.io.wen(wbNumWrite) := false.B 362 coredataModule.io.wen(wbNumWrite) := io.uncache.wen 363 coredataModule.io.fwdMaskWen(wbNumWrite) := false.B 364 coredataModule.io.paddrWen(wbNumWrite) := false.B 365 366 coredataModule.io.waddr(wbNumWrite) := io.uncache.waddr 367 368 coredataModule.io.fwdMaskWdata(wbNumWrite) := DontCare 369 coredataModule.io.paddrWdata(wbNumWrite) := DontCare 370 coredataModule.io.wdata(wbNumWrite) := io.uncache.wdata 371 372 // mem access violation check, gen violationMask 373 (0 until StorePipelineWidth).map(i => { 374 paddrModule.io.violationMdata(i) := io.violation(i).paddr 375 maskModule.io.violationMdata(i) := io.violation(i).mask 376 io.violation(i).violationMask := (paddrModule.io.violationMmask(i).asUInt & maskModule.io.violationMmask(i).asUInt).asBools 377 // VecInit((0 until size).map(j => { 378 // val addrMatch = io.violation(i).paddr(PAddrBits - 1, 3) === data(j).paddr(PAddrBits - 1, 3) 379 // val violationVec = (0 until 8).map(k => data(j).mask(k) && io.violation(i).mask(k)) 380 // Cat(violationVec).orR() && addrMatch 381 // })) 382 }) 383 384 // refill missed load 385 def mergeRefillData(refill: UInt, fwd: UInt, fwdMask: UInt): UInt = { 386 val res = Wire(Vec(8, UInt(8.W))) 387 (0 until 8).foreach(i => { 388 res(i) := Mux(fwdMask(i), fwd(8 * (i + 1) - 1, 8 * i), refill(8 * (i + 1) - 1, 8 * i)) 389 }) 390 res.asUInt 391 } 392 393 // gen paddr match mask 394 paddrModule.io.refillMdata := io.refill.paddr 395 (0 until size).map(i => { 396 io.refill.matchMask := paddrModule.io.refillMmask 397 // io.refill.matchMask(i) := get_block_addr(data(i).paddr) === get_block_addr(io.refill.paddr) 398 }) 399 400 // refill data according to matchMask, refillMask and refill.valid 401 coredataModule.io.refillData := io.refill.data 402 (0 until size).map(i => { 403 coredataModule.io.mwmask(i) := io.refill.valid && io.refill.matchMask(i) && io.refill.refillMask(i) 404 }) 405 406 // debug data read 407 io.debug := DontCare 408} 409