Memend.scala 7.5 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 9
import chisel3.util.experimental.BoringUtils

Y
Yinan Xu 已提交
10
import xiangshan.cache._
W
William Wang 已提交
11
import bus.tilelink.{TLArbiter, TLCached, TLMasterUtilities, TLParameters}
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))
Y
Yinan Xu 已提交
54
  val lsroqIdx = Output(UInt(LsroqIdxWidth.W))
55
  val uop = Output(new MicroOp) // for replay
Y
Yinan Xu 已提交
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
  val pc = Output(UInt(VAddrBits.W)) //for debug
  val valid = Output(Bool()) //for debug

  val forwardMask = Input(Vec(8, Bool()))
  val forwardData = Input(Vec(8, UInt(8.W)))
}

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))
73
  val commits = Flipped(Vec(CommitWidth, Valid(new RoqCommit)))
Y
Yinan Xu 已提交
74
  val dp1Req = Vec(RenameWidth, Flipped(DecoupledIO(new MicroOp)))
Y
Yinan Xu 已提交
75
  val lsroqIdxs = Output(Vec(RenameWidth, UInt(LsroqIdxWidth.W)))
L
LinJiawei 已提交
76
  val roqDeqPtr = Input(UInt(RoqIdxWidth.W))
Y
Yinan Xu 已提交
77 78 79 80 81
}

class Memend extends XSModule {
  val io = IO(new Bundle{
    val backend = new MemToBackendIO
82 83 84 85 86
    val loadUnitToDcacheVec = Vec(exuParameters.LduCnt, new DCacheWordIO)
    val loadMiss = new DCacheLineIO
    val atomics  = new DCacheWordIO
    val sbufferToDcache = new DCacheLineIO
    val uncache = new DCacheWordIO
87
    val ptw = new TlbPtwIO
Y
Yinan Xu 已提交
88 89
  })

A
Allen 已提交
90
  // inner modules
Y
Yinan Xu 已提交
91 92
  val loadUnits = (0 until exuParameters.LduCnt).map(_ => Module(new LoadUnit))
  val storeUnits = (0 until exuParameters.StuCnt).map(_ => Module(new StoreUnit))
A
Allen 已提交
93
  val atomicsUnit = Module(new AtomicsUnit)
94
  val dtlb = Module(new TLB(Width = DTLBWidth, isDtlb = true))
95
  val lsroq = if(EnableUnifiedLSQ) Module(new Lsroq) else Module(new LsqWrappper) 
96
  val sbuffer = Module(new NewSbuffer)
97 98
  // if you wants to stress test dcache store, use FakeSbuffer
  // val sbuffer = Module(new FakeSbuffer)
Y
Yinan Xu 已提交
99

A
Allen 已提交
100
  // dtlb
101
  io.ptw <> dtlb.io.ptw
Y
Yinan Xu 已提交
102

W
William Wang 已提交
103
  // LoadUnit
Y
Yinan Xu 已提交
104
  for (i <- 0 until exuParameters.LduCnt) {
A
Allen 已提交
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
    // 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 已提交
121
  }
122

W
William Wang 已提交
123
  // StoreUnit
Y
Yinan Xu 已提交
124
  for (i <- 0 until exuParameters.StuCnt) {
A
Allen 已提交
125 126 127
    // get input form dispatch
    storeUnits(i).io.stin        <> io.backend.stin(i)
    storeUnits(i).io.redirect    <> io.backend.redirect
Y
Yinan Xu 已提交
128 129
    storeUnits(i).io.tlbFeedback <> io.backend.tlbFeedback(exuParameters.LduCnt + i)

A
Allen 已提交
130 131 132 133 134
    // 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 已提交
135 136
  }

A
Allen 已提交
137 138 139 140 141
  // Lsroq
  lsroq.io.stout       <> io.backend.stout
  lsroq.io.commits     <> io.backend.commits
  lsroq.io.dp1Req      <> io.backend.dp1Req
  lsroq.io.lsroqIdxs   <> io.backend.lsroqIdxs
Y
Yinan Xu 已提交
142
  lsroq.io.brqRedirect := io.backend.redirect
L
LinJiawei 已提交
143
  lsroq.io.roqDeqPtr := io.backend.roqDeqPtr
Y
Yinan Xu 已提交
144
  io.backend.replayAll <> lsroq.io.rollback
145

A
Allen 已提交
146 147 148
  lsroq.io.dcache      <> io.loadMiss
  lsroq.io.uncache     <> io.uncache

Y
Yinan Xu 已提交
149
  // LSROQ to store buffer
A
Allen 已提交
150 151 152 153
  lsroq.io.sbuffer     <> sbuffer.io.in

  // Sbuffer
  sbuffer.io.dcache <> io.sbufferToDcache
A
Allen 已提交
154 155

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

A
Allen 已提交
167
  // TODO: make 0/1 configurable
A
Allen 已提交
168 169 170
  // AtomicsUnit
  // AtomicsUnit will override other control signials,
  // as atomics insts (LR/SC/AMO) will block the pipeline
171 172
  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
173 174
  // amo should always go through store issue queue 0
  assert(!st1_atomics)
175

176 177 178 179 180
  atomicsUnit.io.dtlb.resp.valid := false.B
  atomicsUnit.io.dtlb.resp.bits  := DontCare
  atomicsUnit.io.out.ready       := false.B

  // dispatch 0 takes priority
181 182 183 184 185 186
  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 }
187 188
  }

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

191
  // for atomics, do not let them enter store unit
192 193
  when (st0_atomics) { storeUnits(0).io.stin.valid := false.B }
  when (st1_atomics) { storeUnits(1).io.stin.valid := false.B }
194

195
  when(atomicsUnit.io.dtlb.req.valid) {
A
Allen 已提交
196
    dtlb.io.requestor(0) <> atomicsUnit.io.dtlb // TODO: check it later
197 198 199 200
    // 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 已提交
201
  }
202 203 204 205 206 207 208 209 210

  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 已提交
211
  atomicsUnit.io.redirect <> io.backend.redirect
A
Allen 已提交
212 213 214

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