xref: /XiangShan/src/main/scala/xiangshan/mem/pipeline/StoreUnit.scala (revision b086c6da80b5e7e939f9ce8dde0b13f881c26a65)
1package xiangshan.mem
2
3import chisel3._
4import chisel3.util._
5import utils._
6import xiangshan._
7import xiangshan.cache._
8
9// Store Pipeline Stage 0
10// Generate addr, use addr to query DCache and DTLB
11class StoreUnit_S0 extends XSModule {
12  val io = IO(new Bundle() {
13    val in = Flipped(Decoupled(new ExuInput))
14    val out = Decoupled(new LsPipelineBundle)
15    val dtlbReq = DecoupledIO(new TlbReq)
16  })
17
18  // send req to dtlb
19  val saddr = io.in.bits.src1 + io.in.bits.uop.ctrl.imm
20
21  io.dtlbReq.bits.vaddr := saddr
22  io.dtlbReq.valid := io.in.valid
23  io.dtlbReq.bits.cmd := TlbCmd.write
24  io.dtlbReq.bits.roqIdx := io.in.bits.uop.roqIdx
25  io.dtlbReq.bits.debug.pc := io.in.bits.uop.cf.pc
26
27  io.out.bits := DontCare
28  io.out.bits.vaddr := saddr
29
30  io.out.bits.data := genWdata(io.in.bits.src2, io.in.bits.uop.ctrl.fuOpType(1,0))
31  when(io.in.bits.uop.ctrl.src2Type === SrcType.fp){
32    io.out.bits.data := io.in.bits.src2
33  } // not not touch fp store raw data
34  io.out.bits.uop := io.in.bits.uop
35  io.out.bits.miss := DontCare
36  io.out.bits.mask := genWmask(io.out.bits.vaddr, io.in.bits.uop.ctrl.fuOpType(1,0))
37  io.out.valid := io.in.valid
38  io.in.ready := io.out.ready
39
40  // exception check
41  val addrAligned = LookupTree(io.in.bits.uop.ctrl.fuOpType(1,0), List(
42    "b00".U   -> true.B,              //b
43    "b01".U   -> (io.out.bits.vaddr(0) === 0.U),   //h
44    "b10".U   -> (io.out.bits.vaddr(1,0) === 0.U), //w
45    "b11".U   -> (io.out.bits.vaddr(2,0) === 0.U)  //d
46  ))
47  io.out.bits.uop.cf.exceptionVec(storeAddrMisaligned) := !addrAligned
48
49}
50
51// Load Pipeline Stage 1
52// TLB resp (send paddr to dcache)
53class StoreUnit_S1 extends XSModule {
54  val io = IO(new Bundle() {
55    val in = Flipped(Decoupled(new LsPipelineBundle))
56    val out = Decoupled(new LsPipelineBundle)
57    // val fp_out = Decoupled(new LsPipelineBundle)
58    val lsq = ValidIO(new LsPipelineBundle)
59    val dtlbResp = Flipped(DecoupledIO(new TlbResp))
60    val tlbFeedback = ValidIO(new TlbFeedback)
61  })
62
63  val s1_paddr = io.dtlbResp.bits.paddr
64  val s1_tlb_miss = io.dtlbResp.bits.miss
65
66  io.in.ready := true.B
67
68  io.dtlbResp.ready := true.B // TODO: why dtlbResp needs a ready?
69
70  // Send TLB feedback to store issue queue
71  io.tlbFeedback.valid := io.in.valid
72  io.tlbFeedback.bits.hit := !s1_tlb_miss
73  io.tlbFeedback.bits.roqIdx := io.in.bits.uop.roqIdx
74  XSDebug(io.tlbFeedback.valid,
75    "S1 Store: tlbHit: %d roqIdx: %d\n",
76    io.tlbFeedback.bits.hit,
77    io.tlbFeedback.bits.roqIdx.asUInt
78  )
79
80
81  // get paddr from dtlb, check if rollback is needed
82  // writeback store inst to lsq
83  io.lsq.valid := io.in.valid && !s1_tlb_miss// TODO: && ! FP
84  io.lsq.bits := io.in.bits
85  io.lsq.bits.paddr := s1_paddr
86  io.lsq.bits.miss := false.B
87  io.lsq.bits.mmio := AddressSpace.isMMIO(s1_paddr)
88  io.lsq.bits.uop.cf.exceptionVec(storePageFault) := io.dtlbResp.bits.excp.pf.st
89
90  // mmio inst with exception will be writebacked immediately
91  val hasException = io.out.bits.uop.cf.exceptionVec.asUInt.orR
92  io.out.valid := io.in.valid && (!io.out.bits.mmio || hasException) && !s1_tlb_miss
93  io.out.bits := io.lsq.bits
94
95  // encode data for fp store
96  when(io.in.bits.uop.ctrl.src2Type === SrcType.fp){
97	  io.lsq.bits.data := genWdata(ieee(io.in.bits.data), io.in.bits.uop.ctrl.fuOpType(1,0))
98	}
99
100}
101
102class StoreUnit_S2 extends XSModule {
103  val io = IO(new Bundle() {
104    val in = Flipped(Decoupled(new LsPipelineBundle))
105    val stout = DecoupledIO(new ExuOutput) // writeback store
106  })
107
108  io.in.ready := true.B
109
110  io.stout.valid := io.in.valid
111  io.stout.bits.uop := io.in.bits.uop
112  io.stout.bits.data := DontCare
113  io.stout.bits.redirectValid := false.B
114  io.stout.bits.redirect := DontCare
115  io.stout.bits.brUpdate := DontCare
116  io.stout.bits.debug.isMMIO := io.in.bits.mmio
117  io.stout.bits.fflags := DontCare
118
119}
120
121class StoreUnit extends XSModule {
122  val io = IO(new Bundle() {
123    val stin = Flipped(Decoupled(new ExuInput))
124    val redirect = Flipped(ValidIO(new Redirect))
125    val tlbFeedback = ValidIO(new TlbFeedback)
126    val dtlb = new TlbRequestIO()
127    val lsq = ValidIO(new LsPipelineBundle)
128    val stout = DecoupledIO(new ExuOutput) // writeback store
129  })
130
131  val store_s0 = Module(new StoreUnit_S0)
132  val store_s1 = Module(new StoreUnit_S1)
133  val store_s2 = Module(new StoreUnit_S2)
134
135  store_s0.io.in <> io.stin
136  store_s0.io.dtlbReq <> io.dtlb.req
137
138  PipelineConnect(store_s0.io.out, store_s1.io.in, true.B, store_s0.io.out.bits.uop.roqIdx.needFlush(io.redirect))
139
140  store_s1.io.lsq <> io.lsq // send result to sq
141  store_s1.io.dtlbResp <> io.dtlb.resp
142  store_s1.io.tlbFeedback <> io.tlbFeedback
143
144  PipelineConnect(store_s1.io.out, store_s2.io.in, true.B, store_s1.io.out.bits.uop.roqIdx.needFlush(io.redirect))
145
146  store_s2.io.stout <> io.stout
147
148  private def printPipeLine(pipeline: LsPipelineBundle, cond: Bool, name: String): Unit = {
149    XSDebug(cond,
150      p"$name" + p" pc ${Hexadecimal(pipeline.uop.cf.pc)} " +
151        p"addr ${Hexadecimal(pipeline.vaddr)} -> ${Hexadecimal(pipeline.paddr)} " +
152        p"op ${Binary(pipeline.uop.ctrl.fuOpType)} " +
153        p"data ${Hexadecimal(pipeline.data)} " +
154        p"mask ${Hexadecimal(pipeline.mask)}\n"
155    )
156  }
157
158  printPipeLine(store_s0.io.out.bits, store_s0.io.out.valid, "S0")
159  printPipeLine(store_s1.io.out.bits, store_s1.io.out.valid, "S1")
160
161}
162