Memend.scala 7.4 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)))
Y
Yinan Xu 已提交
76 77 78 79 80
}

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

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

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

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

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

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

A
Allen 已提交
136 137 138 139 140
  // 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 已提交
141 142
  lsroq.io.brqRedirect := io.backend.redirect
  io.backend.replayAll <> lsroq.io.rollback
143

A
Allen 已提交
144 145 146
  lsroq.io.dcache      <> io.loadMiss
  lsroq.io.uncache     <> io.uncache

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

  // Sbuffer
  sbuffer.io.dcache <> io.sbufferToDcache
A
Allen 已提交
152 153

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

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

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

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

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

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

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

  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

209
  atomicsUnit.io.dcache        <> io.atomics
210
  atomicsUnit.io.flush_sbuffer.empty := sbEmpty
A
Allen 已提交
211 212 213

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