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

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)
39
  val func = UInt(6.W) //fixme???
Y
Yinan Xu 已提交
40 41 42 43 44
  val mask = UInt(8.W)
  val data = UInt(XLEN.W)
  val uop = new MicroOp

  val miss = Bool()
45
  val tlbMiss = Bool()
Y
Yinan Xu 已提交
46 47 48 49 50 51 52 53 54 55
  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))
56
  val uop = Output(new MicroOp) // for replay
Y
Yinan Xu 已提交
57 58
  val pc = Output(UInt(VAddrBits.W)) //for debug
  val valid = Output(Bool()) //for debug
59
  
Y
Yinan Xu 已提交
60 61
  val forwardMask = Input(Vec(8, Bool()))
  val forwardData = Input(Vec(8, UInt(8.W)))
62 63

  val lsroqIdx = Output(UInt(LsroqIdxWidth.W))
64
  // val lqIdx = Output(UInt(LoadQueueIdxWidth.W))
65
  val sqIdx = Output(new SqPtr)
Y
Yinan Xu 已提交
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
77
  val tlbFeedback = Vec(exuParameters.LduCnt + exuParameters.StuCnt, ValidIO(new TlbFeedback))
78
  val commits = Flipped(Vec(CommitWidth, Valid(new RoqCommit)))
Y
Yinan Xu 已提交
79
  val dp1Req = Vec(RenameWidth, Flipped(DecoupledIO(new MicroOp)))
80
  val lsIdxs = Output(Vec(RenameWidth, new LSIdx))
81
  val oldestStore = Output(Valid(new RoqPtr))
Y
Yinan Xu 已提交
82
  val roqDeqPtr = Input(new RoqPtr)
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
    val loadUnitToDcacheVec = Vec(exuParameters.LduCnt, new DCacheLoadIO)
92 93 94 95
    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
Y
Yinan Xu 已提交
154
  io.backend.replayAll <> lsroq.io.rollback
155

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

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

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

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

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

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

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

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

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

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

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

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