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