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