1package xiangshan.mem 2 3import chipsalliance.rocketchip.config.Parameters 4import chisel3._ 5import chisel3.util._ 6import utils._ 7import xiangshan._ 8import xiangshan.cache._ 9import xiangshan.cache.{DCacheWordIO, DCacheLineIO, TlbRequestIO, MemoryOpConstants} 10import xiangshan.mem._ 11import xiangshan.backend.roq.RoqPtr 12 13 14// Data module define 15// These data modules are like SyncDataModuleTemplate, but support cam-like ops 16class SQPaddrModule(numEntries: Int, numRead: Int, numWrite: Int, numForward: Int)(implicit p: Parameters) extends XSModule with HasDCacheParameters { 17 val io = IO(new Bundle { 18 val raddr = Input(Vec(numRead, UInt(log2Up(numEntries).W))) 19 val rdata = Output(Vec(numRead, UInt((PAddrBits).W))) 20 val wen = Input(Vec(numWrite, Bool())) 21 val waddr = Input(Vec(numWrite, UInt(log2Up(numEntries).W))) 22 val wdata = Input(Vec(numWrite, UInt((PAddrBits).W))) 23 val forwardMdata = Input(Vec(numForward, UInt((PAddrBits).W))) 24 val forwardMmask = Output(Vec(numForward, Vec(numEntries, Bool()))) 25 }) 26 27 val data = Reg(Vec(numEntries, UInt((PAddrBits).W))) 28 29 // read ports 30 for (i <- 0 until numRead) { 31 io.rdata(i) := data(RegNext(io.raddr(i))) 32 } 33 34 // below is the write ports (with priorities) 35 for (i <- 0 until numWrite) { 36 when (io.wen(i)) { 37 data(io.waddr(i)) := io.wdata(i) 38 } 39 } 40 41 // content addressed match 42 for (i <- 0 until numForward) { 43 for (j <- 0 until numEntries) { 44 io.forwardMmask(i)(j) := io.forwardMdata(i)(PAddrBits-1, 3) === data(j)(PAddrBits-1, 3) 45 } 46 } 47 48 // DataModuleTemplate should not be used when there're any write conflicts 49 for (i <- 0 until numWrite) { 50 for (j <- i+1 until numWrite) { 51 assert(!(io.wen(i) && io.wen(j) && io.waddr(i) === io.waddr(j))) 52 } 53 } 54} 55 56class SQData8Entry(implicit p: Parameters) extends XSBundle { 57 // val paddr = UInt(PAddrBits.W) 58 val valid = Bool() 59 val data = UInt((XLEN/8).W) 60} 61 62class SQData8Module(size: Int, numRead: Int, numWrite: Int, numForward: Int)(implicit p: Parameters) extends XSModule with HasDCacheParameters with HasCircularQueuePtrHelper { 63 val io = IO(new Bundle() { 64 val raddr = Vec(numRead, Input(UInt(log2Up(size).W))) 65 val rdata = Vec(numRead, Output(new SQData8Entry)) 66 val data = new Bundle() { 67 val wen = Vec(numWrite, Input(Bool())) 68 val waddr = Vec(numWrite, Input(UInt(log2Up(size).W))) 69 val wdata = Vec(numWrite, Input(UInt((XLEN/8).W))) 70 } 71 val mask = new Bundle() { 72 val wen = Vec(numWrite, Input(Bool())) 73 val waddr = Vec(numWrite, Input(UInt(log2Up(size).W))) 74 val wdata = Vec(numWrite, Input(Bool())) 75 } 76 77 val needForward = Input(Vec(numForward, Vec(2, UInt(size.W)))) 78 val forwardValid = Vec(numForward, Output(Bool())) 79 val forwardData = Vec(numForward, Output(UInt(8.W))) 80 }) 81 82 io := DontCare 83 84 val data = Reg(Vec(size, new SQData8Entry)) 85 86 // writeback to sq 87 (0 until numWrite).map(i => { 88 when(io.data.wen(i)){ 89 data(io.data.waddr(i)).data := io.data.wdata(i) 90 } 91 }) 92 (0 until numWrite).map(i => { 93 when(io.mask.wen(i)){ 94 data(io.mask.waddr(i)).valid := io.mask.wdata(i) 95 } 96 }) 97 98 // destorequeue read data 99 (0 until numRead).map(i => { 100 io.rdata(i) := data(RegNext(io.raddr(i))) 101 }) 102 103 // DataModuleTemplate should not be used when there're any write conflicts 104 for (i <- 0 until numWrite) { 105 for (j <- i+1 until numWrite) { 106 assert(!(io.data.wen(i) && io.data.wen(j) && io.data.waddr(i) === io.data.waddr(j))) 107 } 108 } 109 for (i <- 0 until numWrite) { 110 for (j <- i+1 until numWrite) { 111 assert(!(io.mask.wen(i) && io.mask.wen(j) && io.mask.waddr(i) === io.mask.waddr(j))) 112 } 113 } 114 115 // forwarding 116 // Compare ringBufferTail (deqPtr) and forward.sqIdx, we have two cases: 117 // (1) if they have the same flag, we need to check range(tail, sqIdx) 118 // (2) if they have different flags, we need to check range(tail, LoadQueueSize) and range(0, sqIdx) 119 // Forward1: Mux(same_flag, range(tail, sqIdx), range(tail, LoadQueueSize)) 120 // Forward2: Mux(same_flag, 0.U, range(0, sqIdx) ) 121 // i.e. forward1 is the target entries with the same flag bits and forward2 otherwise 122 123 // entry with larger index should have higher priority since it's data is younger 124 125 (0 until numForward).map(i => { 126 // parallel fwd logic 127 val matchResultVec = Wire(Vec(size * 2, new FwdEntry)) 128 129 def parallelFwd(xs: Seq[Data]): Data = { 130 ParallelOperation(xs, (a: Data, b: Data) => { 131 val l = a.asTypeOf(new FwdEntry) 132 val r = b.asTypeOf(new FwdEntry) 133 val res = Wire(new FwdEntry) 134 res.valid := l.valid || r.valid 135 res.data := Mux(r.valid, r.data, l.data) 136 res 137 }) 138 } 139 140 // paddrMatch is now included in io.needForward 141 // for (j <- 0 until size) { 142 // paddrMatch(j) := io.forward(i).paddr(PAddrBits - 1, 3) === data(j).paddr(PAddrBits - 1, 3) 143 // } 144 145 for (j <- 0 until size) { 146 val needCheck0 = RegNext(io.needForward(i)(0)(j)) 147 val needCheck1 = RegNext(io.needForward(i)(1)(j)) 148 (0 until XLEN / 8).foreach(k => { 149 matchResultVec(j).valid := needCheck0 && data(j).valid 150 matchResultVec(j).data := data(j).data 151 matchResultVec(size + j).valid := needCheck1 && data(j).valid 152 matchResultVec(size + j).data := data(j).data 153 }) 154 } 155 156 val parallelFwdResult = parallelFwd(matchResultVec).asTypeOf(new FwdEntry) 157 158 io.forwardValid(i) := parallelFwdResult.valid 159 io.forwardData(i) := parallelFwdResult.data 160 161 }) 162} 163 164class SQDataEntry(implicit p: Parameters) extends XSBundle { 165 // val paddr = UInt(PAddrBits.W) 166 val mask = UInt(8.W) 167 val data = UInt(XLEN.W) 168} 169 170class SQDataModule(size: Int, numRead: Int, numWrite: Int, numForward: Int)(implicit p: Parameters) extends XSModule with HasDCacheParameters with HasCircularQueuePtrHelper { 171 val io = IO(new Bundle() { 172 val raddr = Vec(numRead, Input(UInt(log2Up(size).W))) 173 val rdata = Vec(numRead, Output(new SQDataEntry)) 174 val data = new Bundle() { 175 val wen = Vec(numWrite, Input(Bool())) 176 val waddr = Vec(numWrite, Input(UInt(log2Up(size).W))) 177 val wdata = Vec(numWrite, Input(UInt(XLEN.W))) 178 } 179 val mask = new Bundle() { 180 val wen = Vec(numWrite, Input(Bool())) 181 val waddr = Vec(numWrite, Input(UInt(log2Up(size).W))) 182 val wdata = Vec(numWrite, Input(UInt(8.W))) 183 } 184 185 val needForward = Input(Vec(numForward, Vec(2, UInt(size.W)))) 186 val forwardMask = Vec(numForward, Output(Vec(8, Bool()))) 187 val forwardData = Vec(numForward, Output(Vec(8, UInt(8.W)))) 188 }) 189 190 val data8 = Seq.fill(8)(Module(new SQData8Module(size, numRead, numWrite, numForward))) 191 192 // writeback to lq/sq 193 for (i <- 0 until numWrite) { 194 // write to data8 195 for (j <- 0 until 8) { 196 data8(j).io.mask.waddr(i) := io.mask.waddr(i) 197 data8(j).io.mask.wdata(i) := io.mask.wdata(i)(j) 198 data8(j).io.mask.wen(i) := io.mask.wen(i) 199 data8(j).io.data.waddr(i) := io.data.waddr(i) 200 data8(j).io.data.wdata(i) := io.data.wdata(i)(8*(j+1)-1, 8*j) 201 data8(j).io.data.wen(i) := io.data.wen(i) 202 } 203 } 204 205 // destorequeue read data 206 for (i <- 0 until numRead) { 207 for (j <- 0 until 8) { 208 data8(j).io.raddr(i) := io.raddr(i) 209 } 210 io.rdata(i).mask := VecInit((0 until 8).map(j => data8(j).io.rdata(i).valid)).asUInt 211 io.rdata(i).data := VecInit((0 until 8).map(j => data8(j).io.rdata(i).data)).asUInt 212 } 213 214 // DataModuleTemplate should not be used when there're any write conflicts 215 for (i <- 0 until numWrite) { 216 for (j <- i+1 until numWrite) { 217 assert(!(io.data.wen(i) && io.data.wen(j) && io.data.waddr(i) === io.data.waddr(j))) 218 } 219 } 220 for (i <- 0 until numWrite) { 221 for (j <- i+1 until numWrite) { 222 assert(!(io.mask.wen(i) && io.mask.wen(j) && io.mask.waddr(i) === io.mask.waddr(j))) 223 } 224 } 225 226 (0 until numForward).map(i => { 227 // parallel fwd logic 228 for (j <- 0 until 8) { 229 data8(j).io.needForward(i) <> io.needForward(i) 230 io.forwardMask(i) := VecInit((0 until 8).map(j => data8(j).io.forwardValid(i))) 231 io.forwardData(i) := VecInit((0 until 8).map(j => data8(j).io.forwardData(i))) 232 } 233 }) 234} 235