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 ExceptionAddrIO extends XSBundle { 14 val lsIdx = Input(new LSIdx) 15 val isStore = Input(Bool()) 16 val vaddr = Output(UInt(VAddrBits.W)) 17} 18 19 20class LsqEntry extends XSBundle { 21 val vaddr = UInt(VAddrBits.W) // TODO: need opt 22 val paddr = UInt(PAddrBits.W) 23 val op = UInt(6.W) 24 val mask = UInt(8.W) 25 val data = UInt(XLEN.W) 26 val exception = UInt(16.W) // TODO: opt size 27 val mmio = Bool() 28 val fwdMask = Vec(8, Bool()) 29 val fwdData = Vec(8, UInt(8.W)) 30} 31 32// inflight miss block reqs 33class InflightBlockInfo extends XSBundle { 34 val block_addr = UInt(PAddrBits.W) 35 val valid = Bool() 36} 37 38// Load / Store Queue Wrapper for XiangShan Out of Order LSU 39class LsqWrappper extends XSModule with HasDCacheParameters { 40 val io = IO(new Bundle() { 41 val dp1Req = Vec(RenameWidth, Flipped(DecoupledIO(new MicroOp))) 42 val lsIdxs = Output(Vec(RenameWidth, new LSIdx)) 43 val brqRedirect = Input(Valid(new Redirect)) 44 val loadIn = Vec(LoadPipelineWidth, Flipped(Valid(new LsPipelineBundle))) 45 val storeIn = Vec(StorePipelineWidth, Flipped(Valid(new LsPipelineBundle))) 46 val sbuffer = Vec(StorePipelineWidth, Decoupled(new DCacheWordReq)) 47 val ldout = Vec(2, DecoupledIO(new ExuOutput)) // writeback store 48 val stout = Vec(2, DecoupledIO(new ExuOutput)) // writeback store 49 val forward = Vec(LoadPipelineWidth, Flipped(new LoadForwardQueryIO)) 50 val commits = Flipped(Vec(CommitWidth, Valid(new RoqCommit))) 51 val rollback = Output(Valid(new Redirect)) 52 val dcache = new DCacheLineIO 53 val uncache = new DCacheWordIO 54 val roqDeqPtr = Input(new RoqPtr) 55 val oldestStore = Output(Valid(new RoqPtr)) 56 val exceptionAddr = new ExceptionAddrIO 57 }) 58 59 val loadQueue = Module(new LoadQueue) 60 val storeQueue = Module(new StoreQueue) 61 62 // load queue wiring 63 loadQueue.io.dp1Req <> io.dp1Req 64 loadQueue.io.brqRedirect <> io.brqRedirect 65 loadQueue.io.loadIn <> io.loadIn 66 loadQueue.io.storeIn <> io.storeIn 67 loadQueue.io.ldout <> io.ldout 68 loadQueue.io.commits <> io.commits 69 loadQueue.io.rollback <> io.rollback 70 loadQueue.io.dcache <> io.dcache 71 loadQueue.io.roqDeqPtr <> io.roqDeqPtr 72 loadQueue.io.exceptionAddr.lsIdx := io.exceptionAddr.lsIdx 73 loadQueue.io.exceptionAddr.isStore := DontCare 74 75 // store queue wiring 76 // storeQueue.io <> DontCare 77 storeQueue.io.dp1Req <> io.dp1Req 78 storeQueue.io.brqRedirect <> io.brqRedirect 79 storeQueue.io.storeIn <> io.storeIn 80 storeQueue.io.sbuffer <> io.sbuffer 81 storeQueue.io.stout <> io.stout 82 storeQueue.io.commits <> io.commits 83 storeQueue.io.roqDeqPtr <> io.roqDeqPtr 84 storeQueue.io.oldestStore <> io.oldestStore 85 storeQueue.io.exceptionAddr.lsIdx := io.exceptionAddr.lsIdx 86 storeQueue.io.exceptionAddr.isStore := DontCare 87 88 loadQueue.io.forward <> io.forward 89 storeQueue.io.forward <> io.forward // overlap forwardMask & forwardData, DO NOT CHANGE SEQUENCE 90 91 io.exceptionAddr.vaddr := Mux(io.exceptionAddr.isStore, storeQueue.io.exceptionAddr.vaddr, loadQueue.io.exceptionAddr.vaddr) 92 93 // naive uncache arbiter 94 val s_idle :: s_load :: s_store :: Nil = Enum(3) 95 val uncacheState = RegInit(s_idle) 96 97 switch(uncacheState){ 98 is(s_idle){ 99 when(io.uncache.req.fire()){ 100 uncacheState := Mux(loadQueue.io.uncache.req.valid, s_load, s_store) 101 } 102 } 103 is(s_load){ 104 when(io.uncache.resp.fire()){ 105 uncacheState := s_idle 106 } 107 } 108 is(s_store){ 109 when(io.uncache.resp.fire()){ 110 uncacheState := s_idle 111 } 112 } 113 } 114 115 loadQueue.io.uncache := DontCare 116 storeQueue.io.uncache := DontCare 117 loadQueue.io.uncache.resp.valid := false.B 118 storeQueue.io.uncache.resp.valid := false.B 119 when(loadQueue.io.uncache.req.valid){ 120 io.uncache.req <> loadQueue.io.uncache.req 121 }.otherwise{ 122 io.uncache.req <> storeQueue.io.uncache.req 123 } 124 when(uncacheState === s_load){ 125 io.uncache.resp <> loadQueue.io.uncache.resp 126 }.otherwise{ 127 io.uncache.resp <> storeQueue.io.uncache.resp 128 } 129 130 assert(!(loadQueue.io.uncache.req.valid && storeQueue.io.uncache.req.valid)) 131 assert(!(loadQueue.io.uncache.resp.valid && storeQueue.io.uncache.resp.valid)) 132 assert(!((loadQueue.io.uncache.resp.valid || storeQueue.io.uncache.resp.valid) && uncacheState === s_idle)) 133 134 // fix valid, allocate lq / sq index 135 (0 until RenameWidth).map(i => { 136 val isStore = CommitType.lsInstIsStore(io.dp1Req(i).bits.ctrl.commitType) 137 val prevCanIn = if (i == 0) true.B else Cat((0 until i).map(i => io.dp1Req(i).ready)).andR 138 loadQueue.io.dp1Req(i).valid := !isStore && io.dp1Req(i).valid && prevCanIn 139 storeQueue.io.dp1Req(i).valid := isStore && io.dp1Req(i).valid && prevCanIn 140 loadQueue.io.lqIdxs(i) <> io.lsIdxs(i).lqIdx 141 storeQueue.io.sqIdxs(i) <> io.lsIdxs(i).sqIdx 142 io.dp1Req(i).ready := storeQueue.io.dp1Req(i).ready && loadQueue.io.dp1Req(i).ready 143 }) 144} 145