Memend.scala 7.6 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 64
  // val lqIdx = Output(UInt(LoadQueueIdxWidth.W))
  val sqIdx = Output(UInt(StoreQueueIdxWidth.W))
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))
Y
Yinan Xu 已提交
80
  val roqDeqPtr = Input(new RoqPtr)
Y
Yinan Xu 已提交
81 82
}

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

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

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

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

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

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

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

A
Allen 已提交
153 154 155
  lsroq.io.dcache      <> io.loadMiss
  lsroq.io.uncache     <> io.uncache

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

  // Sbuffer
  sbuffer.io.dcache <> io.sbufferToDcache
A
Allen 已提交
161 162

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

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

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

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

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

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

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

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

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