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 LsRoqEntry 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 39// 40// By using this Wrapper, interface of unified lsroq and ldq / stq are the same 41class LsqWrappper extends XSModule with HasDCacheParameters { 42 val io = IO(new Bundle() { 43 val dp1Req = Vec(RenameWidth, Flipped(DecoupledIO(new MicroOp))) 44 val lsIdxs = Output(Vec(RenameWidth, new LSIdx)) 45 val brqRedirect = Input(Valid(new Redirect)) 46 val loadIn = Vec(LoadPipelineWidth, Flipped(Valid(new LsPipelineBundle))) 47 val storeIn = Vec(StorePipelineWidth, Flipped(Valid(new LsPipelineBundle))) 48 val sbuffer = Vec(StorePipelineWidth, Decoupled(new DCacheWordReq)) 49 val ldout = Vec(2, DecoupledIO(new ExuOutput)) // writeback store 50 val stout = Vec(2, DecoupledIO(new ExuOutput)) // writeback store 51 val forward = Vec(LoadPipelineWidth, Flipped(new LoadForwardQueryIO)) 52 val commits = Flipped(Vec(CommitWidth, Valid(new RoqCommit))) 53 val rollback = Output(Valid(new Redirect)) 54 val dcache = new DCacheLineIO 55 val uncache = new DCacheWordIO 56 val roqDeqPtr = Input(new RoqPtr) 57 val oldestStore = Output(Valid(new RoqPtr)) 58 val exceptionAddr = new ExceptionAddrIO 59 }) 60 61 val loadQueue = Module(new LoadQueue) 62 val storeQueue = Module(new StoreQueue) 63 64 // load queue wiring 65 loadQueue.io.dp1Req <> io.dp1Req 66 loadQueue.io.brqRedirect <> io.brqRedirect 67 loadQueue.io.loadIn <> io.loadIn 68 loadQueue.io.storeIn <> io.storeIn 69 loadQueue.io.ldout <> io.ldout 70 loadQueue.io.commits <> io.commits 71 loadQueue.io.rollback <> io.rollback 72 loadQueue.io.dcache <> io.dcache 73 loadQueue.io.roqDeqPtr <> io.roqDeqPtr 74 loadQueue.io.exceptionAddr.lsIdx := io.exceptionAddr.lsIdx 75 loadQueue.io.exceptionAddr.isStore := DontCare 76 77 // store queue wiring 78 // storeQueue.io <> DontCare 79 storeQueue.io.dp1Req <> io.dp1Req 80 storeQueue.io.brqRedirect <> io.brqRedirect 81 storeQueue.io.storeIn <> io.storeIn 82 storeQueue.io.sbuffer <> io.sbuffer 83 storeQueue.io.stout <> io.stout 84 storeQueue.io.commits <> io.commits 85 storeQueue.io.roqDeqPtr <> io.roqDeqPtr 86 storeQueue.io.oldestStore <> io.oldestStore 87 storeQueue.io.exceptionAddr.lsIdx := io.exceptionAddr.lsIdx 88 storeQueue.io.exceptionAddr.isStore := DontCare 89 90 loadQueue.io.forward <> io.forward 91 storeQueue.io.forward <> io.forward // overlap forwardMask & forwardData, DO NOT CHANGE SEQUENCE 92 93 io.exceptionAddr.vaddr := Mux(io.exceptionAddr.isStore, storeQueue.io.exceptionAddr.vaddr, loadQueue.io.exceptionAddr.vaddr) 94 95 // naive uncache arbiter 96 val s_idle :: s_load :: s_store :: Nil = Enum(3) 97 val uncacheState = RegInit(s_idle) 98 99 switch(uncacheState){ 100 is(s_idle){ 101 when(io.uncache.req.fire()){ 102 uncacheState := Mux(loadQueue.io.uncache.req.valid, s_load, s_store) 103 } 104 } 105 is(s_load){ 106 when(io.uncache.resp.fire()){ 107 uncacheState := s_idle 108 } 109 } 110 is(s_store){ 111 when(io.uncache.resp.fire()){ 112 uncacheState := s_idle 113 } 114 } 115 } 116 117 loadQueue.io.uncache := DontCare 118 storeQueue.io.uncache := DontCare 119 loadQueue.io.uncache.resp.valid := false.B 120 storeQueue.io.uncache.resp.valid := false.B 121 when(loadQueue.io.uncache.req.valid){ 122 io.uncache.req <> loadQueue.io.uncache.req 123 }.otherwise{ 124 io.uncache.req <> storeQueue.io.uncache.req 125 } 126 when(uncacheState === s_load){ 127 io.uncache.resp <> loadQueue.io.uncache.resp 128 }.otherwise{ 129 io.uncache.resp <> storeQueue.io.uncache.resp 130 } 131 132 assert(!(loadQueue.io.uncache.req.valid && storeQueue.io.uncache.req.valid)) 133 assert(!(loadQueue.io.uncache.resp.valid && storeQueue.io.uncache.resp.valid)) 134 assert(!((loadQueue.io.uncache.resp.valid || storeQueue.io.uncache.resp.valid) && uncacheState === s_idle)) 135 136 // fix valid, allocate lq / sq index 137 (0 until RenameWidth).map(i => { 138 val isStore = CommitType.lsInstIsStore(io.dp1Req(i).bits.ctrl.commitType) 139 val prevCanIn = if (i == 0) true.B else Cat((0 until i).map(i => io.dp1Req(i).ready)).andR 140 loadQueue.io.dp1Req(i).valid := !isStore && io.dp1Req(i).valid && prevCanIn 141 storeQueue.io.dp1Req(i).valid := isStore && io.dp1Req(i).valid && prevCanIn 142 loadQueue.io.lqIdxs(i) <> io.lsIdxs(i).lqIdx 143 storeQueue.io.sqIdxs(i) <> io.lsIdxs(i).sqIdx 144 io.dp1Req(i).ready := storeQueue.io.dp1Req(i).ready && loadQueue.io.dp1Req(i).ready 145 }) 146} 147