Memend.scala 7.7 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)
Y
Yinan Xu 已提交
82 83
}

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

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

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

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

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

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

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

A
Allen 已提交
155 156 157
  lsroq.io.dcache      <> io.loadMiss
  lsroq.io.uncache     <> io.uncache

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

  // Sbuffer
  sbuffer.io.dcache <> io.sbufferToDcache
A
Allen 已提交
163 164

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

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

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

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

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

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

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

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

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