Memend.scala 8.0 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
import chisel3.util.experimental.BoringUtils
Y
Yinan Xu 已提交
9
import xiangshan.backend.roq.RoqPtr
10

Y
Yinan Xu 已提交
11
import xiangshan.cache._
W
William Wang 已提交
12
import bus.tilelink.{TLArbiter, TLCached, TLMasterUtilities, TLParameters}
Y
Yinan Xu 已提交
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54

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))
55
  val uop = Output(new MicroOp) // for replay
Y
Yinan Xu 已提交
56 57
  val pc = Output(UInt(VAddrBits.W)) //for debug
  val valid = Output(Bool()) //for debug
58
  
Y
Yinan Xu 已提交
59 60
  val forwardMask = Input(Vec(8, Bool()))
  val forwardData = Input(Vec(8, UInt(8.W)))
61 62

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

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))
77
  val commits = Flipped(Vec(CommitWidth, Valid(new RoqCommit)))
Y
Yinan Xu 已提交
78
  val dp1Req = Vec(RenameWidth, Flipped(DecoupledIO(new MicroOp)))
79
  val lsIdxs = Output(Vec(RenameWidth, new LSIdx))
80
  val oldestStore = Output(Valid(new RoqPtr))
Y
Yinan Xu 已提交
81
  val roqDeqPtr = Input(new RoqPtr)
82
  val exceptionAddr = new ExceptionAddrIO
Y
Yinan Xu 已提交
83 84
}

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

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

A
Allen 已提交
109
  // dtlb
110
  io.ptw <> dtlb.io.ptw
Y
Yinan Xu 已提交
111

W
William Wang 已提交
112
  // LoadUnit
Y
Yinan Xu 已提交
113
  for (i <- 0 until exuParameters.LduCnt) {
A
Allen 已提交
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
    // 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 已提交
130
  }
131

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

A
Allen 已提交
139 140 141 142 143
    // 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 已提交
144 145
  }

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

Y
Yinan Xu 已提交
155
  io.backend.replayAll <> lsroq.io.rollback
156

A
Allen 已提交
157 158 159
  lsroq.io.dcache      <> io.loadMiss
  lsroq.io.uncache     <> io.uncache

Y
Yinan Xu 已提交
160
  // LSROQ to store buffer
A
Allen 已提交
161 162 163 164
  lsroq.io.sbuffer     <> sbuffer.io.in

  // Sbuffer
  sbuffer.io.dcache <> io.sbufferToDcache
A
Allen 已提交
165 166

  // flush sbuffer
167
  val fenceFlush = WireInit(false.B)
168
  val atomicsFlush = atomicsUnit.io.flush_sbuffer.valid
169 170 171 172
  BoringUtils.addSink(fenceFlush, "FenceUnitSbufferFlush")
  val sbEmpty = WireInit(false.B)
  sbEmpty := sbuffer.io.flush.empty
  BoringUtils.addSource(sbEmpty, "SBufferEmpty")
A
Allen 已提交
173 174
  // if both of them tries to flush sbuffer at the same time
  // something must have gone wrong
175 176
  assert(!(fenceFlush && atomicsFlush))
  sbuffer.io.flush.valid := fenceFlush || atomicsFlush
Y
Yinan Xu 已提交
177

A
Allen 已提交
178
  // TODO: make 0/1 configurable
A
Allen 已提交
179 180 181
  // AtomicsUnit
  // AtomicsUnit will override other control signials,
  // as atomics insts (LR/SC/AMO) will block the pipeline
182 183
  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
184 185
  // amo should always go through store issue queue 0
  assert(!st1_atomics)
186

187 188 189 190 191
  atomicsUnit.io.dtlb.resp.valid := false.B
  atomicsUnit.io.dtlb.resp.bits  := DontCare
  atomicsUnit.io.out.ready       := false.B

  // dispatch 0 takes priority
192 193 194 195 196 197
  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 }
198 199
  }

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

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

206
  when(atomicsUnit.io.dtlb.req.valid) {
A
Allen 已提交
207
    dtlb.io.requestor(0) <> atomicsUnit.io.dtlb // TODO: check it later
208 209 210 211
    // 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 已提交
212
  }
213 214 215 216 217 218 219 220 221

  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 已提交
222
  atomicsUnit.io.redirect <> io.backend.redirect
A
Allen 已提交
223 224 225

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

  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 已提交
235
}