LSQWrapper.scala 4.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
package xiangshan.mem

import chisel3._
import chisel3.util._
import utils._
import xiangshan._
import xiangshan.cache._
import xiangshan.cache.{DCacheWordIO, DCacheLineIO, TlbRequestIO, MemoryOpConstants}
import xiangshan.backend.LSUOpType
import xiangshan.mem._
11
import xiangshan.backend.roq.RoqPtr
12 13 14 15 16 17 18

// Load / Store Queue Wrapper for XiangShan Out of Order LSU
//
// By using this Wrapper, interface of unified lsroq and ldq / stq are the same 
class LsqWrappper extends XSModule with HasDCacheParameters with NeedImpl {
  val io = IO(new Bundle() {
    val dp1Req = Vec(RenameWidth, Flipped(DecoupledIO(new MicroOp)))
19
    val lsIdxs = Output(Vec(RenameWidth, new LSIdx))
20 21 22 23 24 25 26 27 28 29 30
    val brqRedirect = Input(Valid(new Redirect))
    val loadIn = Vec(LoadPipelineWidth, Flipped(Valid(new LsPipelineBundle)))
    val storeIn = Vec(StorePipelineWidth, Flipped(Valid(new LsPipelineBundle)))
    val sbuffer = Vec(StorePipelineWidth, Decoupled(new DCacheWordReq))
    val ldout = Vec(2, DecoupledIO(new ExuOutput)) // writeback store
    val stout = Vec(2, DecoupledIO(new ExuOutput)) // writeback store
    val forward = Vec(LoadPipelineWidth, Flipped(new LoadForwardQueryIO))
    val commits = Flipped(Vec(CommitWidth, Valid(new RoqCommit)))
    val rollback = Output(Valid(new Redirect))
    val dcache = new DCacheLineIO
    val uncache = new DCacheWordIO
31
    val roqDeqPtr = Input(new RoqPtr)
32 33
  })
  
34 35
  if(EnableUnifiedLSQ){
    val lsroq = Module(new Lsroq)
36 37 38 39 40 41 42 43 44 45 46 47 48 49

    lsroq.io.dp1Req <> io.dp1Req
    lsroq.io.brqRedirect <> io.brqRedirect
    lsroq.io.loadIn <> io.loadIn
    lsroq.io.storeIn <> io.storeIn
    lsroq.io.sbuffer <> io.sbuffer
    lsroq.io.ldout <> io.ldout
    lsroq.io.stout <> io.stout
    lsroq.io.forward <> io.forward
    lsroq.io.commits <> io.commits
    lsroq.io.rollback <> io.rollback
    lsroq.io.dcache <> io.dcache
    lsroq.io.uncache <> io.uncache
    lsroq.io.roqDeqPtr <> io.roqDeqPtr
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
    (0 until RenameWidth).map(i => {
      io.lsIdxs(i).lsroqIdx := lsroq.io.lsroqIdxs(i)
    })
  } else {
    val loadQueue = Module(new LoadQueue)
    val storeQueue = Module(new StoreQueue)
    
    // load queue wiring
    loadQueue.io.dp1Req <> io.dp1Req
    loadQueue.io.brqRedirect <> io.brqRedirect
    loadQueue.io.loadIn <> io.loadIn
    loadQueue.io.storeIn <> io.storeIn
    loadQueue.io.ldout <> io.ldout
    loadQueue.io.commits <> io.commits
    loadQueue.io.rollback <> io.rollback
    loadQueue.io.dcache <> io.dcache
    loadQueue.io.roqDeqPtr <> io.roqDeqPtr
    
    // store queue wiring
    // storeQueue.io <> DontCare
    storeQueue.io.dp1Req <> io.dp1Req
    storeQueue.io.brqRedirect <> io.brqRedirect
    storeQueue.io.storeIn <> io.storeIn
    storeQueue.io.sbuffer <> io.sbuffer
    storeQueue.io.stout <> io.stout
    storeQueue.io.commits <> io.commits
    storeQueue.io.roqDeqPtr <> io.roqDeqPtr
    
78 79 80
    loadQueue.io.forward <> io.forward
    storeQueue.io.forward <> io.forward // overlap forwardMask & forwardData, DO NOT CHANGE SEQUENCE

81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
    // naive uncache arbiter
    val s_idle :: s_load :: s_store :: Nil = Enum(3)
    val uncacheState = RegInit(s_idle)

    switch(uncacheState){
      is(s_idle){
        when(io.uncache.req.fire()){
          uncacheState := Mux(loadQueue.io.uncache.req.valid, s_load, s_store)
        }
      }
      is(s_load){
        when(io.uncache.resp.fire()){
          uncacheState := s_idle
        }
      }
      is(s_store){
        when(io.uncache.resp.fire()){
          uncacheState := s_idle
        }
      }
    }

    loadQueue.io.uncache := DontCare
    storeQueue.io.uncache := DontCare
105 106
    loadQueue.io.uncache.resp.valid := false.B
    storeQueue.io.uncache.resp.valid := false.B
107 108 109 110 111 112 113 114 115 116 117 118 119 120
    when(loadQueue.io.uncache.req.valid){
      io.uncache.req <> loadQueue.io.uncache.req
    }.otherwise{
      io.uncache.req <> storeQueue.io.uncache.req
    }
    when(uncacheState === s_load){
      io.uncache.resp <> loadQueue.io.uncache.resp
    }.otherwise{
      io.uncache.resp <> storeQueue.io.uncache.resp
    }
    io.uncache.s1_kill := false.B

    assert(!(loadQueue.io.uncache.req.valid && storeQueue.io.uncache.req.valid))
    assert(!(loadQueue.io.uncache.resp.valid && storeQueue.io.uncache.resp.valid))
121
    assert(!((loadQueue.io.uncache.resp.valid || storeQueue.io.uncache.resp.valid) && uncacheState === s_idle))
122 123 124
    
    // fix valid, allocate lq / sq index
    (0 until RenameWidth).map(i => {
125
      val isStore = CommitType.lsInstIsStore(io.dp1Req(i).bits.ctrl.commitType)
126 127 128
      val prevCanIn = if (i == 0) true.B else Cat((0 until i).map(i => io.dp1Req(i).ready)).andR
      loadQueue.io.dp1Req(i).valid := !isStore && io.dp1Req(i).valid && prevCanIn
      storeQueue.io.dp1Req(i).valid := isStore && io.dp1Req(i).valid && prevCanIn
129 130
      loadQueue.io.lqIdxs(i) <> io.lsIdxs(i).lqIdx
      storeQueue.io.sqIdxs(i) <> io.lsIdxs(i).sqIdx
131
      io.dp1Req(i).ready := storeQueue.io.dp1Req(i).ready && loadQueue.io.dp1Req(i).ready
132 133
    })
  }
134
}