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