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