Memend.scala 8.1 KB
Newer Older
Y
Yinan Xu 已提交
1 2 3 4 5 6
package xiangshan.mem

import chisel3._
import chisel3.util._
import xiangshan._
import utils._
Y
Yinan Xu 已提交
7
import xiangshan.backend.roq.RoqPtr
Y
Yinan Xu 已提交
8
import xiangshan.cache._
L
LinJiawei 已提交
9
import xiangshan.backend.fu.FenceToSbuffer
Y
Yinan Xu 已提交
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35

object genWmask {
  def apply(addr: UInt, sizeEncode: UInt): UInt = {
    (LookupTree(sizeEncode, List(
      "b00".U -> 0x1.U, //0001 << addr(2:0)
      "b01".U -> 0x3.U, //0011
      "b10".U -> 0xf.U, //1111
      "b11".U -> 0xff.U //11111111
    )) << addr(2, 0)).asUInt()
  }
}

object genWdata {
  def apply(data: UInt, sizeEncode: UInt): UInt = {
    LookupTree(sizeEncode, List(
      "b00".U -> Fill(8, data(7, 0)),
      "b01".U -> Fill(4, data(15, 0)),
      "b10".U -> Fill(2, data(31, 0)),
      "b11".U -> data
    ))
  }
}

class LsPipelineBundle extends XSBundle {
  val vaddr = UInt(VAddrBits.W)
  val paddr = UInt(PAddrBits.W)
36
  val func = UInt(6.W) //fixme???
Y
Yinan Xu 已提交
37 38 39 40 41
  val mask = UInt(8.W)
  val data = UInt(XLEN.W)
  val uop = new MicroOp

  val miss = Bool()
42
  val tlbMiss = Bool()
Y
Yinan Xu 已提交
43 44 45 46 47 48 49 50 51 52
  val mmio = Bool()
  val rollback = Bool()

  val forwardMask = Vec(8, Bool())
  val forwardData = Vec(8, UInt(8.W))
}

class LoadForwardQueryIO extends XSBundle {
  val paddr = Output(UInt(PAddrBits.W))
  val mask = Output(UInt(8.W))
53
  val uop = Output(new MicroOp) // for replay
Y
Yinan Xu 已提交
54 55
  val pc = Output(UInt(VAddrBits.W)) //for debug
  val valid = Output(Bool()) //for debug
56
  
Y
Yinan Xu 已提交
57 58
  val forwardMask = Input(Vec(8, Bool()))
  val forwardData = Input(Vec(8, UInt(8.W)))
59 60

  val lsroqIdx = Output(UInt(LsroqIdxWidth.W))
61
  // val lqIdx = Output(UInt(LoadQueueIdxWidth.W))
62
  val sqIdx = Output(new SqPtr)
Y
Yinan Xu 已提交
63 64 65 66 67 68 69 70 71 72 73
}

class MemToBackendIO extends XSBundle {
  val ldin = Vec(exuParameters.LduCnt, Flipped(Decoupled(new ExuInput)))
  val stin = Vec(exuParameters.StuCnt, Flipped(Decoupled(new ExuInput)))
  val ldout = Vec(exuParameters.LduCnt, Decoupled(new ExuOutput))
  val stout = Vec(exuParameters.StuCnt, Decoupled(new ExuOutput))
  val redirect = Flipped(ValidIO(new Redirect))
  // replay all instructions form dispatch
  val replayAll = ValidIO(new Redirect)
  // replay mem instructions form Load Queue/Store Queue
74
  val tlbFeedback = Vec(exuParameters.LduCnt + exuParameters.StuCnt, ValidIO(new TlbFeedback))
75
  val commits = Flipped(Vec(CommitWidth, Valid(new RoqCommit)))
Y
Yinan Xu 已提交
76
  val dp1Req = Vec(RenameWidth, Flipped(DecoupledIO(new MicroOp)))
77
  val lsIdxs = Output(Vec(RenameWidth, new LSIdx))
78
  val oldestStore = Output(Valid(new RoqPtr))
Y
Yinan Xu 已提交
79
  val roqDeqPtr = Input(new RoqPtr)
80
  val exceptionAddr = new ExceptionAddrIO
L
LinJiawei 已提交
81 82
  val fenceToSbuffer = Flipped(new FenceToSbuffer)
  val sfence = Input(new SfenceBundle)
L
LinJiawei 已提交
83
  val csr = Input(new TlbCsrBundle)
Y
Yinan Xu 已提交
84 85
}

W
William Wang 已提交
86 87 88
// Memory pipeline wrapper
//
// Wrap the whole memory access pipeline as a single module "Memend"
Y
Yinan Xu 已提交
89 90 91
class Memend extends XSModule {
  val io = IO(new Bundle{
    val backend = new MemToBackendIO
92
    val loadUnitToDcacheVec = Vec(exuParameters.LduCnt, new DCacheLoadIO)
93 94 95 96
    val loadMiss = new DCacheLineIO
    val atomics  = new DCacheWordIO
    val sbufferToDcache = new DCacheLineIO
    val uncache = new DCacheWordIO
97
    val ptw = new TlbPtwIO
Y
Yinan Xu 已提交
98 99
  })

A
Allen 已提交
100
  // inner modules
Y
Yinan Xu 已提交
101 102
  val loadUnits = (0 until exuParameters.LduCnt).map(_ => Module(new LoadUnit))
  val storeUnits = (0 until exuParameters.StuCnt).map(_ => Module(new StoreUnit))
A
Allen 已提交
103
  val atomicsUnit = Module(new AtomicsUnit)
104
  val dtlb = Module(new TLB(Width = DTLBWidth, isDtlb = true))
105
  val lsroq = Module(new LsqWrappper) 
106
  val sbuffer = Module(new NewSbuffer)
107 108
  // if you wants to stress test dcache store, use FakeSbuffer
  // val sbuffer = Module(new FakeSbuffer)
Y
Yinan Xu 已提交
109

A
Allen 已提交
110
  // dtlb
111
  io.ptw <> dtlb.io.ptw
L
LinJiawei 已提交
112
  dtlb.io.sfence <> io.backend.sfence
L
LinJiawei 已提交
113
  dtlb.io.csr <> io.backend.csr
Y
Yinan Xu 已提交
114

W
William Wang 已提交
115
  // LoadUnit
Y
Yinan Xu 已提交
116
  for (i <- 0 until exuParameters.LduCnt) {
A
Allen 已提交
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
    // get input form dispatch
    loadUnits(i).io.ldin          <> io.backend.ldin(i)
    loadUnits(i).io.ldout         <> io.backend.ldout(i)
    loadUnits(i).io.redirect      <> io.backend.redirect
    loadUnits(i).io.tlbFeedback   <> io.backend.tlbFeedback(i)
    // dtlb access
    loadUnits(i).io.dtlb          <> dtlb.io.requestor(i)
    // dcache access
    loadUnits(i).io.dcache        <> io.loadUnitToDcacheVec(i)
    // forward
    loadUnits(i).io.lsroq.forward <> lsroq.io.forward(i)
    loadUnits(i).io.sbuffer       <> sbuffer.io.forward(i)

    // passdown to lsroq
    lsroq.io.loadIn(i)            <> loadUnits(i).io.lsroq.loadIn
    lsroq.io.ldout(i)             <> loadUnits(i).io.lsroq.ldout
Y
Yinan Xu 已提交
133
  }
134

W
William Wang 已提交
135
  // StoreUnit
Y
Yinan Xu 已提交
136
  for (i <- 0 until exuParameters.StuCnt) {
A
Allen 已提交
137 138 139
    // get input form dispatch
    storeUnits(i).io.stin        <> io.backend.stin(i)
    storeUnits(i).io.redirect    <> io.backend.redirect
Y
Yinan Xu 已提交
140 141
    storeUnits(i).io.tlbFeedback <> io.backend.tlbFeedback(exuParameters.LduCnt + i)

A
Allen 已提交
142 143 144 145 146
    // dtlb access
    storeUnits(i).io.dtlb        <> dtlb.io.requestor(exuParameters.LduCnt + i) // FIXME

    // passdown to lsroq
    storeUnits(i).io.lsroq       <> lsroq.io.storeIn(i)
Y
Yinan Xu 已提交
147 148
  }

A
Allen 已提交
149 150 151 152
  // Lsroq
  lsroq.io.stout       <> io.backend.stout
  lsroq.io.commits     <> io.backend.commits
  lsroq.io.dp1Req      <> io.backend.dp1Req
153
  lsroq.io.oldestStore <> io.backend.oldestStore
154
  lsroq.io.lsIdxs   <> io.backend.lsIdxs
Y
Yinan Xu 已提交
155
  lsroq.io.brqRedirect := io.backend.redirect
L
LinJiawei 已提交
156
  lsroq.io.roqDeqPtr := io.backend.roqDeqPtr
157

Y
Yinan Xu 已提交
158
  io.backend.replayAll <> lsroq.io.rollback
159

A
Allen 已提交
160 161 162
  lsroq.io.dcache      <> io.loadMiss
  lsroq.io.uncache     <> io.uncache

Y
Yinan Xu 已提交
163
  // LSROQ to store buffer
A
Allen 已提交
164 165 166 167
  lsroq.io.sbuffer     <> sbuffer.io.in

  // Sbuffer
  sbuffer.io.dcache <> io.sbufferToDcache
A
Allen 已提交
168 169

  // flush sbuffer
170
  val fenceFlush = WireInit(false.B)
171
  val atomicsFlush = atomicsUnit.io.flush_sbuffer.valid
L
LinJiawei 已提交
172 173 174
  fenceFlush := io.backend.fenceToSbuffer.flushSb
  val sbEmpty = sbuffer.io.flush.empty
  io.backend.fenceToSbuffer.sbIsEmpty := sbEmpty
A
Allen 已提交
175 176
  // if both of them tries to flush sbuffer at the same time
  // something must have gone wrong
177 178
  assert(!(fenceFlush && atomicsFlush))
  sbuffer.io.flush.valid := fenceFlush || atomicsFlush
Y
Yinan Xu 已提交
179

A
Allen 已提交
180
  // TODO: make 0/1 configurable
A
Allen 已提交
181 182 183
  // AtomicsUnit
  // AtomicsUnit will override other control signials,
  // as atomics insts (LR/SC/AMO) will block the pipeline
184 185
  val st0_atomics = io.backend.stin(0).valid && io.backend.stin(0).bits.uop.ctrl.fuType === FuType.mou
  val st1_atomics = io.backend.stin(1).valid && io.backend.stin(1).bits.uop.ctrl.fuType === FuType.mou
186 187
  // amo should always go through store issue queue 0
  assert(!st1_atomics)
188

189 190 191
  atomicsUnit.io.dtlb.resp.valid := false.B
  atomicsUnit.io.dtlb.resp.bits  := DontCare
  atomicsUnit.io.out.ready       := false.B
192
  atomicsUnit.io.dtlb.req.ready  := dtlb.io.requestor(0).req.ready
193 194

  // dispatch 0 takes priority
195 196 197 198 199 200
  atomicsUnit.io.in.valid := st0_atomics || st1_atomics
  atomicsUnit.io.in.bits  := Mux(st0_atomics, io.backend.stin(0).bits, io.backend.stin(1).bits)
  when (st0_atomics) {
    io.backend.stin(0).ready := atomicsUnit.io.in.ready
    // explitly set st1 ready to false, do not let it fire
    when (st1_atomics) { io.backend.stin(1).ready := false.B }
201 202
  }

203
  when (!st0_atomics && st1_atomics) { io.backend.stin(1).ready := atomicsUnit.io.in.ready }
204

205
  // for atomics, do not let them enter store unit
206 207
  when (st0_atomics) { storeUnits(0).io.stin.valid := false.B }
  when (st1_atomics) { storeUnits(1).io.stin.valid := false.B }
208

209
  when(atomicsUnit.io.dtlb.req.valid) {
A
Allen 已提交
210
    dtlb.io.requestor(0) <> atomicsUnit.io.dtlb // TODO: check it later
211 212 213 214
    // take load unit 0's tlb port
    // make sure not to disturb loadUnit
    assert(!loadUnits(0).io.dtlb.req.valid)
    loadUnits(0).io.dtlb.resp.valid := false.B
W
William Wang 已提交
215
  }
216 217 218 219 220 221 222 223 224

  when(atomicsUnit.io.tlbFeedback.valid) {
    assert(!storeUnits(0).io.tlbFeedback.valid)
    atomicsUnit.io.tlbFeedback <> io.backend.tlbFeedback(exuParameters.LduCnt + 0)
  }

  atomicsUnit.io.dcache        <> io.atomics
  atomicsUnit.io.flush_sbuffer.empty := sbEmpty

W
William Wang 已提交
225
  atomicsUnit.io.redirect <> io.backend.redirect
A
Allen 已提交
226 227 228

  when(atomicsUnit.io.out.valid){
    io.backend.ldout(0) <> atomicsUnit.io.out
229 230 231
    // take load unit 0's write back port
    assert(!loadUnits(0).io.ldout.valid)
    loadUnits(0).io.ldout.ready := false.B
W
William Wang 已提交
232
  }
233 234 235 236 237

  lsroq.io.exceptionAddr.lsIdx := io.backend.exceptionAddr.lsIdx
  lsroq.io.exceptionAddr.isStore := io.backend.exceptionAddr.isStore
  io.backend.exceptionAddr.vaddr := Mux(atomicsUnit.io.exceptionAddr.valid, atomicsUnit.io.exceptionAddr.bits, lsroq.io.exceptionAddr.vaddr)

Y
Yinan Xu 已提交
238
}