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 13 14class SQDataEntry extends XSBundle { 15// val vaddr = UInt(VAddrBits.W) // TODO: need opt 16 val paddr = UInt(PAddrBits.W) 17 val mask = UInt(8.W) 18 val data = UInt(XLEN.W) 19// val exception = UInt(16.W) // TODO: opt size 20} 21 22class StoreQueueData(size: Int, numRead: Int, numWrite: Int, numForward: Int) extends XSModule with HasDCacheParameters with HasCircularQueuePtrHelper { 23 val io = IO(new Bundle() { 24 val raddr = Vec(numRead, Input(UInt(log2Up(size).W))) 25 val rdata = Vec(numRead, Output(new SQDataEntry)) 26 val wen = Vec(numWrite, Input(Bool())) 27 val waddr = Vec(numWrite, Input(UInt(log2Up(size).W))) 28 val wdata = Vec(numWrite, Input(new SQDataEntry)) 29 val debug = Vec(size, Output(new SQDataEntry)) 30 31 val needForward = Input(Vec(numForward, Vec(2, UInt(size.W)))) 32 val forward = Vec(numForward, Flipped(new LoadForwardQueryIO)) 33 34 def forwardQuery(numForward: Int, paddr: UInt, needForward1: Data, needForward2: Data): Unit = { 35 this.needForward(numForward)(0) := needForward1 36 this.needForward(numForward)(1) := needForward2 37 this.forward(numForward).paddr := paddr 38 } 39 }) 40 41 io := DontCare 42 43 val data = Reg(Vec(size, new SQDataEntry)) 44 45 // writeback to lq/sq 46 (0 until numWrite).map(i => { 47 when(io.wen(i)){ 48 data(io.waddr(i)) := io.wdata(i) 49 } 50 }) 51 52 // destorequeue read data 53 (0 until numRead).map(i => { 54 io.rdata(i) := data(io.raddr(i)) 55 }) 56 57 // DataModuleTemplate should not be used when there're any write conflicts 58 for (i <- 0 until numWrite) { 59 for (j <- i+1 until numWrite) { 60 assert(!(io.wen(i) && io.wen(j) && io.waddr(i) === io.waddr(j))) 61 } 62 } 63 64 // forwarding 65 // Compare ringBufferTail (deqPtr) and forward.sqIdx, we have two cases: 66 // (1) if they have the same flag, we need to check range(tail, sqIdx) 67 // (2) if they have different flags, we need to check range(tail, LoadQueueSize) and range(0, sqIdx) 68 // Forward1: Mux(same_flag, range(tail, sqIdx), range(tail, LoadQueueSize)) 69 // Forward2: Mux(same_flag, 0.U, range(0, sqIdx) ) 70 // i.e. forward1 is the target entries with the same flag bits and forward2 otherwise 71 72 // entry with larger index should have higher priority since it's data is younger 73 74 (0 until numForward).map(i => { 75 val forwardMask1 = WireInit(VecInit(Seq.fill(8)(false.B))) 76 val forwardData1 = WireInit(VecInit(Seq.fill(8)(0.U(8.W)))) 77 val forwardMask2 = WireInit(VecInit(Seq.fill(8)(false.B))) 78 val forwardData2 = WireInit(VecInit(Seq.fill(8)(0.U(8.W)))) 79 80 for (j <- 0 until size) { 81 val needCheck = io.forward(i).paddr(PAddrBits - 1, 3) === data(j).paddr(PAddrBits - 1, 3) 82 (0 until XLEN / 8).foreach(k => { 83 when (needCheck && data(j).mask(k)) { 84 when (io.needForward(i)(0)(j)) { 85 forwardMask1(k) := true.B 86 forwardData1(k) := data(j).data(8 * (k + 1) - 1, 8 * k) 87 } 88 when (io.needForward(i)(1)(j)) { 89 forwardMask2(k) := true.B 90 forwardData2(k) := data(j).data(8 * (k + 1) - 1, 8 * k) 91 } 92 XSDebug(io.needForward(i)(0)(j) || io.needForward(i)(1)(j), 93 p"forwarding $k-th byte ${Hexadecimal(data(j).data(8 * (k + 1) - 1, 8 * k))} " + 94 p"from ptr $j\n") 95 } 96 }) 97 } 98 99 // parallel fwd logic 100 val paddrMatch = Wire(Vec(size, Bool())) 101 val matchResultVec = Wire(Vec(size * 2, new FwdEntry)) 102 103 def parallelFwd(xs: Seq[Data]): Data = { 104 ParallelOperation(xs, (a: Data, b: Data) => { 105 val l = a.asTypeOf(new FwdEntry) 106 val r = b.asTypeOf(new FwdEntry) 107 val res = Wire(new FwdEntry) 108 (0 until 8).map(p => { 109 res.mask(p) := l.mask(p) || r.mask(p) 110 res.data(p) := Mux(r.mask(p), r.data(p), l.data(p)) 111 }) 112 res 113 }) 114 } 115 116 for (j <- 0 until size) { 117 paddrMatch(j) := io.forward(i).paddr(PAddrBits - 1, 3) === data(j).paddr(PAddrBits - 1, 3) 118 } 119 120 for (j <- 0 until size) { 121 val needCheck0 = RegNext(paddrMatch(j) && io.needForward(i)(0)(j)) 122 val needCheck1 = RegNext(paddrMatch(j) && io.needForward(i)(1)(j)) 123 (0 until XLEN / 8).foreach(k => { 124 matchResultVec(j).mask(k) := needCheck0 && data(j).mask(k) 125 matchResultVec(j).data(k) := data(j).data(8 * (k + 1) - 1, 8 * k) 126 matchResultVec(size + j).mask(k) := needCheck1 && data(j).mask(k) 127 matchResultVec(size + j).data(k) := data(j).data(8 * (k + 1) - 1, 8 * k) 128 }) 129 } 130 131 val parallelFwdResult = parallelFwd(matchResultVec).asTypeOf(new FwdEntry) 132 133 io.forward(i).forwardMask := parallelFwdResult.mask 134 io.forward(i).forwardData := parallelFwdResult.data 135 136 }) 137 138 io.debug := data 139}