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 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))
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 63
  // val lqIdx = Output(UInt(LoadQueueIdxWidth.W))
  val sqIdx = Output(UInt(StoreQueueIdxWidth.W))
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))
L
LinJiawei 已提交
79
  val roqDeqPtr = Input(UInt(RoqIdxWidth.W))
Y
Yinan Xu 已提交
80 81
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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