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

import chisel3._
import chisel3.util._
5
import chisel3.util.experimental.BoringUtils
Y
Yinan Xu 已提交
6 7
import xiangshan._
import utils._
8 9
import chisel3.util.experimental.BoringUtils

Y
Yinan Xu 已提交
10
import xiangshan.cache._
W
William Wang 已提交
11
import bus.tilelink.{TLArbiter, TLCached, TLMasterUtilities, TLParameters}
Y
Yinan Xu 已提交
12 13 14 15 16 17 18 19 20 21 22 23 24 25

object LSUOpType {
  def lb   = "b000000".U
  def lh   = "b000001".U
  def lw   = "b000010".U
  def ld   = "b000011".U
  def lbu  = "b000100".U
  def lhu  = "b000101".U
  def lwu  = "b000110".U
  def ldu  = "b000111".U
  def sb   = "b001000".U
  def sh   = "b001001".U
  def sw   = "b001010".U
  def sd   = "b001011".U
26
  
Y
Yinan Xu 已提交
27 28 29 30 31 32 33 34 35 36 37
  def lr      = "b100010".U
  def sc      = "b100011".U
  def amoswap = "b100001".U
  def amoadd  = "b100000".U
  def amoxor  = "b100100".U
  def amoand  = "b101100".U
  def amoor   = "b101000".U
  def amomin  = "b110000".U
  def amomax  = "b110100".U
  def amominu = "b111000".U
  def amomaxu = "b111100".U
38
  
Y
Yinan Xu 已提交
39 40
  def isStore(func: UInt): Bool = func(3)
  def isAtom(func: UInt): Bool = func(5)
41
  
Y
Yinan Xu 已提交
42 43 44 45
  def atomW = "010".U
  def atomD = "011".U
}

A
Allen 已提交
46
object DCacheAtomicsType {
47 48
  def miss      = "b00".U
  def mmio      = "b01".U
A
Allen 已提交
49
  def atomics      = "b10".U
50 51
}

Y
Yinan Xu 已提交
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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
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)
  val func = UInt(6.W)
  val mask = UInt(8.W)
  val data = UInt(XLEN.W)
  val uop = new MicroOp

  val miss = Bool()
  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))
Y
Yinan Xu 已提交
93
  val lsroqIdx = Output(UInt(LsroqIdxWidth.W))
94
  val uop = Output(new MicroOp) // for replay
Y
Yinan Xu 已提交
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
  val pc = Output(UInt(VAddrBits.W)) //for debug
  val valid = Output(Bool()) //for debug

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

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
  val tlbFeedback = Vec(exuParameters.LduCnt + exuParameters.LduCnt, ValidIO(new TlbFeedback))
112
  val commits = Flipped(Vec(CommitWidth, Valid(new RoqCommit)))
Y
Yinan Xu 已提交
113
  val dp1Req = Vec(RenameWidth, Flipped(DecoupledIO(new MicroOp)))
Y
Yinan Xu 已提交
114
  val lsroqIdxs = Output(Vec(RenameWidth, UInt(LsroqIdxWidth.W)))
Y
Yinan Xu 已提交
115 116 117 118 119
}

class Memend extends XSModule {
  val io = IO(new Bundle{
    val backend = new MemToBackendIO
120
    val loadUnitToDcacheVec = Vec(exuParameters.LduCnt, new DCacheLoadIO)
A
Allen 已提交
121 122
    val loadMiss = new DCacheLoadIO
    val atomics  = new DCacheLoadIO
123
    val sbufferToDcache = new DCacheStoreIO
L
linjiawei 已提交
124
    val uncache = new DCacheLoadIO
125
    val ptw = new TlbPtwIO
Y
Yinan Xu 已提交
126 127
  })

A
Allen 已提交
128
  // inner modules
Y
Yinan Xu 已提交
129 130
  val loadUnits = (0 until exuParameters.LduCnt).map(_ => Module(new LoadUnit))
  val storeUnits = (0 until exuParameters.StuCnt).map(_ => Module(new StoreUnit))
A
Allen 已提交
131
  val atomicsUnit = Module(new AtomicsUnit)
132
  val dtlb = Module(new TLB(Width = DTLBWidth, isDtlb = true))
Y
Yinan Xu 已提交
133
  val lsroq = Module(new Lsroq)
Y
YikeZhou 已提交
134
  val sbuffer = Module(new Sbuffer)
135 136
  // if you wants to stress test dcache store, use FakeSbuffer
  // val sbuffer = Module(new FakeSbuffer)
Y
Yinan Xu 已提交
137

A
Allen 已提交
138
  // dtlb
139
  io.ptw <> dtlb.io.ptw
Y
Yinan Xu 已提交
140

W
William Wang 已提交
141
  // LoadUnit
Y
Yinan Xu 已提交
142
  for (i <- 0 until exuParameters.LduCnt) {
A
Allen 已提交
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
    // 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 已提交
159
  }
160

W
William Wang 已提交
161
  // StoreUnit
Y
Yinan Xu 已提交
162
  for (i <- 0 until exuParameters.StuCnt) {
A
Allen 已提交
163 164 165
    // get input form dispatch
    storeUnits(i).io.stin        <> io.backend.stin(i)
    storeUnits(i).io.redirect    <> io.backend.redirect
Y
Yinan Xu 已提交
166 167
    storeUnits(i).io.tlbFeedback <> io.backend.tlbFeedback(exuParameters.LduCnt + i)

A
Allen 已提交
168 169 170 171 172
    // 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 已提交
173 174
  }

A
Allen 已提交
175 176 177 178 179
  // Lsroq
  lsroq.io.stout       <> io.backend.stout
  lsroq.io.commits     <> io.backend.commits
  lsroq.io.dp1Req      <> io.backend.dp1Req
  lsroq.io.lsroqIdxs   <> io.backend.lsroqIdxs
Y
Yinan Xu 已提交
180 181
  lsroq.io.brqRedirect := io.backend.redirect
  io.backend.replayAll <> lsroq.io.rollback
182

A
Allen 已提交
183 184 185
  lsroq.io.dcache      <> io.loadMiss
  lsroq.io.uncache     <> io.uncache

Y
Yinan Xu 已提交
186
  // LSROQ to store buffer
A
Allen 已提交
187 188 189 190
  lsroq.io.sbuffer     <> sbuffer.io.in

  // Sbuffer
  sbuffer.io.dcache <> io.sbufferToDcache
A
Allen 已提交
191 192

  // flush sbuffer
193
  val fenceFlush = WireInit(false.B)
194
  val atomicsFlush = atomicsUnit.io.flush_sbuffer.valid
195 196 197 198
  BoringUtils.addSink(fenceFlush, "FenceUnitSbufferFlush")
  val sbEmpty = WireInit(false.B)
  sbEmpty := sbuffer.io.flush.empty
  BoringUtils.addSource(sbEmpty, "SBufferEmpty")
A
Allen 已提交
199 200
  // if both of them tries to flush sbuffer at the same time
  // something must have gone wrong
201 202
  assert(!(fenceFlush && atomicsFlush))
  sbuffer.io.flush.valid := fenceFlush || atomicsFlush
Y
Yinan Xu 已提交
203

A
Allen 已提交
204
  // TODO: make 0/1 configurable
A
Allen 已提交
205 206 207
  // AtomicsUnit
  // AtomicsUnit will override other control signials,
  // as atomics insts (LR/SC/AMO) will block the pipeline
208 209
  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
210

211 212 213 214 215
  atomicsUnit.io.dtlb.resp.valid := false.B
  atomicsUnit.io.dtlb.resp.bits  := DontCare
  atomicsUnit.io.out.ready       := false.B

  // dispatch 0 takes priority
216 217 218 219 220 221
  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 }
222 223
  }

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

226
  // for atomics, do not let them enter store unit
227 228
  when (st0_atomics) { storeUnits(0).io.stin.valid := false.B }
  when (st1_atomics) { storeUnits(1).io.stin.valid := false.B }
229

230
  when(atomicsUnit.io.dtlb.req.valid) {
A
Allen 已提交
231
    dtlb.io.requestor(0) <> atomicsUnit.io.dtlb // TODO: check it later
232 233 234 235
    // 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 已提交
236
  }
237
  atomicsUnit.io.dcache        <> io.atomics
238
  atomicsUnit.io.flush_sbuffer.empty := sbEmpty
A
Allen 已提交
239 240 241

  when(atomicsUnit.io.out.valid){
    io.backend.ldout(0) <> atomicsUnit.io.out
242 243 244
    // take load unit 0's write back port
    assert(!loadUnits(0).io.ldout.valid)
    loadUnits(0).io.ldout.ready := false.B
W
William Wang 已提交
245
  }
Y
Yinan Xu 已提交
246
}