1package xiangshan.mem 2 3import chisel3._ 4import chisel3.util._ 5import utils._ 6import xiangshan._ 7import xiangshan.cache.{DCacheWordIO, TlbRequestIO, TlbCmd, MemoryOpConstants} 8import xiangshan.backend.LSUOpType 9 10class AtomicsUnit extends XSModule with MemoryOpConstants{ 11 val io = IO(new Bundle() { 12 val in = Flipped(Decoupled(new ExuInput)) 13 val out = Decoupled(new ExuOutput) 14 val dcache = new DCacheWordIO 15 val dtlb = new TlbRequestIO 16 val flush_sbuffer = new SbufferFlushBundle 17 val tlbFeedback = ValidIO(new TlbFeedback) 18 val redirect = Flipped(ValidIO(new Redirect)) 19 }) 20 21 //------------------------------------------------------- 22 // Atomics Memory Accsess FSM 23 //------------------------------------------------------- 24 val s_invalid :: s_tlb :: s_flush_sbuffer_req :: s_flush_sbuffer_resp :: s_cache_req :: s_cache_resp :: s_finish :: Nil = Enum(7) 25 val state = RegInit(s_invalid) 26 val in = Reg(new ExuInput()) 27 val atom_override_xtval = RegInit(false.B) 28 // paddr after translation 29 val paddr = Reg(UInt()) 30 // dcache response data 31 val resp_data = Reg(UInt()) 32 val is_lrsc_valid = Reg(Bool()) 33 34 ExcitingUtils.addSource(in.src1, "ATOM_EXECPTION_VADDR") 35 ExcitingUtils.addSource(atom_override_xtval, "ATOM_OVERRIDE_XTVAL") 36 37 // assign default value to output signals 38 io.in.ready := false.B 39 io.out.valid := false.B 40 io.out.bits := DontCare 41 42 io.dcache.req.valid := false.B 43 io.dcache.req.bits := DontCare 44 io.dcache.resp.ready := false.B 45 46 io.dtlb.req.valid := false.B 47 io.dtlb.req.bits := DontCare 48 49 io.flush_sbuffer.valid := false.B 50 51 XSDebug("state: %d\n", state) 52 53 when (state === s_invalid) { 54 io.in.ready := true.B 55 when (io.in.fire()) { 56 in := io.in.bits 57 state := s_tlb 58 } 59 } 60 61 // Send TLB feedback to store issue queue 62 // we send feedback right after we receives request 63 // also, we always treat amo as tlb hit 64 // since we will continue polling tlb all by ourself 65 io.tlbFeedback.valid := RegNext(io.in.fire()) 66 io.tlbFeedback.bits.hit := true.B 67 io.tlbFeedback.bits.roqIdx := in.uop.roqIdx 68 69 70 // tlb translation, manipulating signals && deal with exception 71 when (state === s_tlb) { 72 // send req to dtlb 73 // keep firing until tlb hit 74 io.dtlb.req.valid := true.B 75 io.dtlb.req.bits.vaddr := in.src1 76 io.dtlb.req.bits.roqIdx := in.uop.roqIdx 77 val is_lr = in.uop.ctrl.fuOpType === LSUOpType.lr_w || in.uop.ctrl.fuOpType === LSUOpType.lr_d 78 io.dtlb.req.bits.cmd := Mux(is_lr, TlbCmd.read, TlbCmd.write) 79 io.dtlb.req.bits.debug.pc := in.uop.cf.pc 80 io.dtlb.req.bits.debug.lsroqIdx := in.uop.lsroqIdx // FIXME: need update 81 82 when(io.dtlb.resp.valid && !io.dtlb.resp.bits.miss){ 83 // exception handling 84 val addrAligned = LookupTree(in.uop.ctrl.fuOpType(1,0), List( 85 "b00".U -> true.B, //b 86 "b01".U -> (in.src1(0) === 0.U), //h 87 "b10".U -> (in.src1(1,0) === 0.U), //w 88 "b11".U -> (in.src1(2,0) === 0.U) //d 89 )) 90 in.uop.cf.exceptionVec(storeAddrMisaligned) := !addrAligned 91 in.uop.cf.exceptionVec(storePageFault) := io.dtlb.resp.bits.excp.pf.st 92 in.uop.cf.exceptionVec(loadPageFault) := io.dtlb.resp.bits.excp.pf.ld 93 val exception = !addrAligned || io.dtlb.resp.bits.excp.pf.st || io.dtlb.resp.bits.excp.pf.ld 94 when (exception) { 95 // check for exceptions 96 // if there are exceptions, no need to execute it 97 state := s_finish 98 atom_override_xtval := true.B 99 } .otherwise { 100 paddr := io.dtlb.resp.bits.paddr 101 state := s_flush_sbuffer_req 102 } 103 } 104 } 105 106 107 when (state === s_flush_sbuffer_req) { 108 io.flush_sbuffer.valid := true.B 109 state := s_flush_sbuffer_resp 110 } 111 112 when (state === s_flush_sbuffer_resp) { 113 when (io.flush_sbuffer.empty) { 114 state := s_cache_req 115 } 116 } 117 118 when (state === s_cache_req) { 119 io.dcache.req.valid := true.B 120 io.dcache.req.bits.cmd := LookupTree(in.uop.ctrl.fuOpType, List( 121 LSUOpType.lr_w -> M_XLR, 122 LSUOpType.sc_w -> M_XSC, 123 LSUOpType.amoswap_w -> M_XA_SWAP, 124 LSUOpType.amoadd_w -> M_XA_ADD, 125 LSUOpType.amoxor_w -> M_XA_XOR, 126 LSUOpType.amoand_w -> M_XA_AND, 127 LSUOpType.amoor_w -> M_XA_OR, 128 LSUOpType.amomin_w -> M_XA_MIN, 129 LSUOpType.amomax_w -> M_XA_MAX, 130 LSUOpType.amominu_w -> M_XA_MINU, 131 LSUOpType.amomaxu_w -> M_XA_MAXU, 132 133 LSUOpType.lr_d -> M_XLR, 134 LSUOpType.sc_d -> M_XSC, 135 LSUOpType.amoswap_d -> M_XA_SWAP, 136 LSUOpType.amoadd_d -> M_XA_ADD, 137 LSUOpType.amoxor_d -> M_XA_XOR, 138 LSUOpType.amoand_d -> M_XA_AND, 139 LSUOpType.amoor_d -> M_XA_OR, 140 LSUOpType.amomin_d -> M_XA_MIN, 141 LSUOpType.amomax_d -> M_XA_MAX, 142 LSUOpType.amominu_d -> M_XA_MINU, 143 LSUOpType.amomaxu_d -> M_XA_MAXU 144 )) 145 146 io.dcache.req.bits.addr := paddr 147 io.dcache.req.bits.data := genWdata(in.src2, in.uop.ctrl.fuOpType(1,0)) 148 // TODO: atomics do need mask: fix mask 149 io.dcache.req.bits.mask := genWmask(paddr, in.uop.ctrl.fuOpType(1,0)) 150 io.dcache.req.bits.meta.id := DontCare 151 io.dcache.req.bits.meta.paddr := paddr 152 io.dcache.req.bits.meta.tlb_miss := false.B 153 io.dcache.req.bits.meta.replay := false.B 154 155 when(io.dcache.req.fire()){ 156 state := s_cache_resp 157 } 158 } 159 160 when (state === s_cache_resp) { 161 io.dcache.resp.ready := true.B 162 when(io.dcache.resp.fire()) { 163 is_lrsc_valid := io.dcache.resp.bits.meta.id 164 val rdata = io.dcache.resp.bits.data 165 val rdataSel = LookupTree(paddr(2, 0), List( 166 "b000".U -> rdata(63, 0), 167 "b001".U -> rdata(63, 8), 168 "b010".U -> rdata(63, 16), 169 "b011".U -> rdata(63, 24), 170 "b100".U -> rdata(63, 32), 171 "b101".U -> rdata(63, 40), 172 "b110".U -> rdata(63, 48), 173 "b111".U -> rdata(63, 56) 174 )) 175 176 resp_data := LookupTree(in.uop.ctrl.fuOpType, List( 177 LSUOpType.lr_w -> SignExt(rdataSel(31, 0), XLEN), 178 LSUOpType.sc_w -> rdata, 179 LSUOpType.amoswap_w -> SignExt(rdataSel(31, 0), XLEN), 180 LSUOpType.amoadd_w -> SignExt(rdataSel(31, 0), XLEN), 181 LSUOpType.amoxor_w -> SignExt(rdataSel(31, 0), XLEN), 182 LSUOpType.amoand_w -> SignExt(rdataSel(31, 0), XLEN), 183 LSUOpType.amoor_w -> SignExt(rdataSel(31, 0), XLEN), 184 LSUOpType.amomin_w -> SignExt(rdataSel(31, 0), XLEN), 185 LSUOpType.amomax_w -> SignExt(rdataSel(31, 0), XLEN), 186 LSUOpType.amominu_w -> SignExt(rdataSel(31, 0), XLEN), 187 LSUOpType.amomaxu_w -> SignExt(rdataSel(31, 0), XLEN), 188 189 LSUOpType.lr_d -> SignExt(rdataSel(63, 0), XLEN), 190 LSUOpType.sc_d -> rdata, 191 LSUOpType.amoswap_d -> SignExt(rdataSel(63, 0), XLEN), 192 LSUOpType.amoadd_d -> SignExt(rdataSel(63, 0), XLEN), 193 LSUOpType.amoxor_d -> SignExt(rdataSel(63, 0), XLEN), 194 LSUOpType.amoand_d -> SignExt(rdataSel(63, 0), XLEN), 195 LSUOpType.amoor_d -> SignExt(rdataSel(63, 0), XLEN), 196 LSUOpType.amomin_d -> SignExt(rdataSel(63, 0), XLEN), 197 LSUOpType.amomax_d -> SignExt(rdataSel(63, 0), XLEN), 198 LSUOpType.amominu_d -> SignExt(rdataSel(63, 0), XLEN), 199 LSUOpType.amomaxu_d -> SignExt(rdataSel(63, 0), XLEN) 200 )) 201 202 state := s_finish 203 } 204 } 205 206 when (state === s_finish) { 207 io.out.valid := true.B 208 io.out.bits.uop := in.uop 209 io.out.bits.uop.diffTestDebugLrScValid := is_lrsc_valid 210 io.out.bits.data := resp_data 211 io.out.bits.redirectValid := false.B 212 io.out.bits.redirect := DontCare 213 io.out.bits.brUpdate := DontCare 214 io.out.bits.debug.isMMIO := AddressSpace.isMMIO(paddr) 215 when (io.out.fire()) { 216 XSDebug("atomics writeback: pc %x data %x\n", io.out.bits.uop.cf.pc, io.dcache.resp.bits.data) 217 state := s_invalid 218 } 219 } 220 221 when(io.redirect.valid){ 222 atom_override_xtval := false.B 223 } 224} 225