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

import chisel3._
import chisel3.util._
import xiangshan._
import utils._
7
import chisel3.util.experimental.BoringUtils
Y
Yinan Xu 已提交
8
import xiangshan.backend.roq.RoqPtr
Y
Yinan Xu 已提交
9
import xiangshan.cache._
W
William Wang 已提交
10
import bus.tilelink.{TLArbiter, TLCached, TLMasterUtilities, TLParameters}
L
LinJiawei 已提交
11
import xiangshan.backend.exu.FenceToSbuffer
Y
Yinan Xu 已提交
12 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

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

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

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

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

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

A
Allen 已提交
110
  // dtlb
111
  io.ptw <> dtlb.io.ptw
L
LinJiawei 已提交
112
  dtlb.io.sfence <> io.backend.sfence
Y
Yinan Xu 已提交
113

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

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

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

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

Y
Yinan Xu 已提交
157
  io.backend.replayAll <> lsroq.io.rollback
158

A
Allen 已提交
159 160 161
  lsroq.io.dcache      <> io.loadMiss
  lsroq.io.uncache     <> io.uncache

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

  // Sbuffer
  sbuffer.io.dcache <> io.sbufferToDcache
A
Allen 已提交
167 168

  // flush sbuffer
169
  val fenceFlush = WireInit(false.B)
170
  val atomicsFlush = atomicsUnit.io.flush_sbuffer.valid
L
LinJiawei 已提交
171 172 173
  fenceFlush := io.backend.fenceToSbuffer.flushSb
  val sbEmpty = sbuffer.io.flush.empty
  io.backend.fenceToSbuffer.sbIsEmpty := sbEmpty
A
Allen 已提交
174 175
  // if both of them tries to flush sbuffer at the same time
  // something must have gone wrong
176 177
  assert(!(fenceFlush && atomicsFlush))
  sbuffer.io.flush.valid := fenceFlush || atomicsFlush
Y
Yinan Xu 已提交
178

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

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

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

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

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

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

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

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

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