xref: /XiangShan/src/main/scala/xiangshan/frontend/IFU.scala (revision 09c6f1dd83448ac60a0bb7980c3e4e524df66de0)
1*09c6f1ddSLingrui98/***************************************************************************************
2*09c6f1ddSLingrui98* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3*09c6f1ddSLingrui98* Copyright (c) 2020-2021 Peng Cheng Laboratory
4*09c6f1ddSLingrui98*
5*09c6f1ddSLingrui98* XiangShan is licensed under Mulan PSL v2.
6*09c6f1ddSLingrui98* You can use this software according to the terms and conditions of the Mulan PSL v2.
7*09c6f1ddSLingrui98* You may obtain a copy of Mulan PSL v2 at:
8*09c6f1ddSLingrui98*          http://license.coscl.org.cn/MulanPSL2
9*09c6f1ddSLingrui98*
10*09c6f1ddSLingrui98* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11*09c6f1ddSLingrui98* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12*09c6f1ddSLingrui98* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13*09c6f1ddSLingrui98*
14*09c6f1ddSLingrui98* See the Mulan PSL v2 for more details.
15*09c6f1ddSLingrui98***************************************************************************************/
16*09c6f1ddSLingrui98
17*09c6f1ddSLingrui98package xiangshan.frontend
18*09c6f1ddSLingrui98
19*09c6f1ddSLingrui98import chipsalliance.rocketchip.config.Parameters
20*09c6f1ddSLingrui98import chisel3._
21*09c6f1ddSLingrui98import chisel3.util._
22*09c6f1ddSLingrui98import xiangshan._
23*09c6f1ddSLingrui98import xiangshan.cache._
24*09c6f1ddSLingrui98import xiangshan.cache.mmu._
25*09c6f1ddSLingrui98import chisel3.experimental.verification
26*09c6f1ddSLingrui98import utils._
27*09c6f1ddSLingrui98
28*09c6f1ddSLingrui98trait HasInstrMMIOConst extends HasXSParameter with HasIFUConst{
29*09c6f1ddSLingrui98  def mmioBusWidth = 64
30*09c6f1ddSLingrui98  def mmioBusBytes = mmioBusWidth /8
31*09c6f1ddSLingrui98  def mmioBeats = FetchWidth * 4 * 8 / mmioBusWidth
32*09c6f1ddSLingrui98  def mmioMask  = VecInit(List.fill(PredictWidth)(true.B)).asUInt
33*09c6f1ddSLingrui98  def mmioBusAligned(pc :UInt): UInt = align(pc, mmioBusBytes)
34*09c6f1ddSLingrui98}
35*09c6f1ddSLingrui98
36*09c6f1ddSLingrui98trait HasIFUConst extends HasXSParameter {
37*09c6f1ddSLingrui98  def align(pc: UInt, bytes: Int): UInt = Cat(pc(VAddrBits-1, log2Ceil(bytes)), 0.U(log2Ceil(bytes).W))
38*09c6f1ddSLingrui98  // def groupAligned(pc: UInt)  = align(pc, groupBytes)
39*09c6f1ddSLingrui98  // def packetAligned(pc: UInt) = align(pc, packetBytes)
40*09c6f1ddSLingrui98}
41*09c6f1ddSLingrui98
42*09c6f1ddSLingrui98class IfuToFtqIO(implicit p:Parameters) extends XSBundle {
43*09c6f1ddSLingrui98  val pdWb = Valid(new PredecodeWritebackBundle)
44*09c6f1ddSLingrui98}
45*09c6f1ddSLingrui98
46*09c6f1ddSLingrui98class FtqInterface(implicit p: Parameters) extends XSBundle {
47*09c6f1ddSLingrui98  val fromFtq = Flipped(new FtqToIfuIO)
48*09c6f1ddSLingrui98  val toFtq   = new IfuToFtqIO
49*09c6f1ddSLingrui98}
50*09c6f1ddSLingrui98
51*09c6f1ddSLingrui98class ICacheInterface(implicit p: Parameters) extends XSBundle {
52*09c6f1ddSLingrui98  val toIMeta       = Decoupled(new ICacheReadBundle)
53*09c6f1ddSLingrui98  val toIData       = Decoupled(new ICacheReadBundle)
54*09c6f1ddSLingrui98  val toMissQueue   = Vec(2,Decoupled(new ICacheMissReq))
55*09c6f1ddSLingrui98  val fromIMeta     = Input(new ICacheMetaRespBundle)
56*09c6f1ddSLingrui98  val fromIData     = Input(new ICacheDataRespBundle)
57*09c6f1ddSLingrui98  val fromMissQueue = Vec(2,Flipped(Decoupled(new ICacheMissResp)))
58*09c6f1ddSLingrui98}
59*09c6f1ddSLingrui98
60*09c6f1ddSLingrui98class NewIFUIO(implicit p: Parameters) extends XSBundle {
61*09c6f1ddSLingrui98  val ftqInter        = new FtqInterface
62*09c6f1ddSLingrui98  val icacheInter     = new ICacheInterface
63*09c6f1ddSLingrui98  val toIbuffer       = Decoupled(new FetchToIBuffer)
64*09c6f1ddSLingrui98  val iTLBInter       = Vec(2, new BlockTlbRequestIO)
65*09c6f1ddSLingrui98}
66*09c6f1ddSLingrui98
67*09c6f1ddSLingrui98// record the situation in which fallThruAddr falls into
68*09c6f1ddSLingrui98// the middle of an RVI inst
69*09c6f1ddSLingrui98class LastHalfInfo(implicit p: Parameters) extends XSBundle {
70*09c6f1ddSLingrui98  val valid = Bool()
71*09c6f1ddSLingrui98  val middlePC = UInt(VAddrBits.W)
72*09c6f1ddSLingrui98  def matchThisBlock(startAddr: UInt) = valid && middlePC === startAddr
73*09c6f1ddSLingrui98}
74*09c6f1ddSLingrui98
75*09c6f1ddSLingrui98class IfuToPreDecode(implicit p: Parameters) extends XSBundle {
76*09c6f1ddSLingrui98  val data          = if(HasCExtension) Vec(PredictWidth + 1, UInt(16.W)) else Vec(PredictWidth, UInt(32.W))
77*09c6f1ddSLingrui98  val startAddr     = UInt(VAddrBits.W)
78*09c6f1ddSLingrui98  val fallThruAddr  = UInt(VAddrBits.W)
79*09c6f1ddSLingrui98  val fallThruError = Bool()
80*09c6f1ddSLingrui98  val isDoubleLine  = Bool()
81*09c6f1ddSLingrui98  val ftqOffset     = Valid(UInt(log2Ceil(PredictWidth).W))
82*09c6f1ddSLingrui98  val target        = UInt(VAddrBits.W)
83*09c6f1ddSLingrui98  val pageFault     = Vec(2, Bool())
84*09c6f1ddSLingrui98  val accessFault   = Vec(2, Bool())
85*09c6f1ddSLingrui98  val instValid     = Bool()
86*09c6f1ddSLingrui98  val lastHalfMatch = Bool()
87*09c6f1ddSLingrui98  val oversize      = Bool()
88*09c6f1ddSLingrui98}
89*09c6f1ddSLingrui98
90*09c6f1ddSLingrui98class NewIFU(implicit p: Parameters) extends XSModule with HasICacheParameters
91*09c6f1ddSLingrui98{
92*09c6f1ddSLingrui98  println(s"icache ways: ${nWays} sets:${nSets}")
93*09c6f1ddSLingrui98  val io = IO(new NewIFUIO)
94*09c6f1ddSLingrui98  val (toFtq, fromFtq)    = (io.ftqInter.toFtq, io.ftqInter.fromFtq)
95*09c6f1ddSLingrui98  val (toMeta, toData, meta_resp, data_resp) =  (io.icacheInter.toIMeta, io.icacheInter.toIData, io.icacheInter.fromIMeta, io.icacheInter.fromIData)
96*09c6f1ddSLingrui98  val (toMissQueue, fromMissQueue) = (io.icacheInter.toMissQueue, io.icacheInter.fromMissQueue)
97*09c6f1ddSLingrui98  val (toITLB, fromITLB) = (VecInit(io.iTLBInter.map(_.req)), VecInit(io.iTLBInter.map(_.resp)))
98*09c6f1ddSLingrui98
99*09c6f1ddSLingrui98  def isCrossLineReq(start: UInt, end: UInt): Bool = start(blockOffBits) ^ end(blockOffBits)
100*09c6f1ddSLingrui98
101*09c6f1ddSLingrui98  def isLastInCacheline(fallThruAddr: UInt): Bool = fallThruAddr(blockOffBits - 1, 1) === 0.U
102*09c6f1ddSLingrui98
103*09c6f1ddSLingrui98
104*09c6f1ddSLingrui98  //---------------------------------------------
105*09c6f1ddSLingrui98  //  Fetch Stage 1 :
106*09c6f1ddSLingrui98  //  * Send req to ICache Meta/Data
107*09c6f1ddSLingrui98  //  * Check whether need 2 line fetch
108*09c6f1ddSLingrui98  //---------------------------------------------
109*09c6f1ddSLingrui98
110*09c6f1ddSLingrui98  val f0_valid                             = fromFtq.req.valid
111*09c6f1ddSLingrui98  val f0_ftq_req                           = fromFtq.req.bits
112*09c6f1ddSLingrui98  val f0_situation                         = VecInit(Seq(isCrossLineReq(f0_ftq_req.startAddr, f0_ftq_req.fallThruAddr), isLastInCacheline(f0_ftq_req.fallThruAddr)))
113*09c6f1ddSLingrui98  val f0_doubleLine                        = f0_situation(0) || f0_situation(1)
114*09c6f1ddSLingrui98  val f0_vSetIdx                           = VecInit(get_idx((f0_ftq_req.startAddr)), get_idx(f0_ftq_req.fallThruAddr))
115*09c6f1ddSLingrui98  val f0_fire                              = fromFtq.req.fire()
116*09c6f1ddSLingrui98
117*09c6f1ddSLingrui98  val f0_flush, f1_flush, f2_flush, f3_flush = WireInit(false.B)
118*09c6f1ddSLingrui98  val from_bpu_f0_flush, from_bpu_f1_flush, from_bpu_f2_flush, from_bpu_f3_flush = WireInit(false.B)
119*09c6f1ddSLingrui98
120*09c6f1ddSLingrui98  from_bpu_f0_flush := fromFtq.flushFromBpu.shouldFlushByStage2(f0_ftq_req.ftqIdx) ||
121*09c6f1ddSLingrui98                       fromFtq.flushFromBpu.shouldFlushByStage3(f0_ftq_req.ftqIdx)
122*09c6f1ddSLingrui98
123*09c6f1ddSLingrui98  val f3_redirect = WireInit(false.B)
124*09c6f1ddSLingrui98  f3_flush := fromFtq.redirect.valid
125*09c6f1ddSLingrui98  f2_flush := f3_flush || f3_redirect
126*09c6f1ddSLingrui98  f1_flush := f2_flush || from_bpu_f1_flush
127*09c6f1ddSLingrui98  f0_flush := f1_flush || from_bpu_f0_flush
128*09c6f1ddSLingrui98
129*09c6f1ddSLingrui98  val f1_ready, f2_ready, f3_ready         = WireInit(false.B)
130*09c6f1ddSLingrui98
131*09c6f1ddSLingrui98  //fetch: send addr to Meta/TLB and Data simultaneously
132*09c6f1ddSLingrui98  val fetch_req = List(toMeta, toData)
133*09c6f1ddSLingrui98  for(i <- 0 until 2) {
134*09c6f1ddSLingrui98    fetch_req(i).valid := f0_fire
135*09c6f1ddSLingrui98    fetch_req(i).bits.isDoubleLine := f0_doubleLine
136*09c6f1ddSLingrui98    fetch_req(i).bits.vSetIdx := f0_vSetIdx
137*09c6f1ddSLingrui98  }
138*09c6f1ddSLingrui98
139*09c6f1ddSLingrui98  fromFtq.req.ready := fetch_req(0).ready && fetch_req(1).ready && f1_ready && GTimer() > 500.U
140*09c6f1ddSLingrui98
141*09c6f1ddSLingrui98  //---------------------------------------------
142*09c6f1ddSLingrui98  //  Fetch Stage 2 :
143*09c6f1ddSLingrui98  //  * Send req to ITLB and TLB Response (Get Paddr)
144*09c6f1ddSLingrui98  //  * ICache Response (Get Meta and Data)
145*09c6f1ddSLingrui98  //  * Hit Check (Generate hit signal and hit vector)
146*09c6f1ddSLingrui98  //  * Get victim way
147*09c6f1ddSLingrui98  //---------------------------------------------
148*09c6f1ddSLingrui98
149*09c6f1ddSLingrui98  //TODO: handle fetch exceptions
150*09c6f1ddSLingrui98
151*09c6f1ddSLingrui98  val tlbRespAllValid = WireInit(false.B)
152*09c6f1ddSLingrui98
153*09c6f1ddSLingrui98  val f1_valid      = RegInit(false.B)
154*09c6f1ddSLingrui98  val f1_ftq_req    = RegEnable(next = f0_ftq_req,    enable=f0_fire)
155*09c6f1ddSLingrui98  val f1_situation  = RegEnable(next = f0_situation,  enable=f0_fire)
156*09c6f1ddSLingrui98  val f1_doubleLine = RegEnable(next = f0_doubleLine, enable=f0_fire)
157*09c6f1ddSLingrui98  val f1_vSetIdx    = RegEnable(next = f0_vSetIdx,    enable=f0_fire)
158*09c6f1ddSLingrui98  val f1_fire       = f1_valid && tlbRespAllValid && f2_ready
159*09c6f1ddSLingrui98
160*09c6f1ddSLingrui98  f1_ready := f2_ready && tlbRespAllValid || !f1_valid
161*09c6f1ddSLingrui98
162*09c6f1ddSLingrui98  from_bpu_f1_flush := fromFtq.flushFromBpu.shouldFlushByStage3(f1_ftq_req.ftqIdx)
163*09c6f1ddSLingrui98
164*09c6f1ddSLingrui98  val preDecoder      = Module(new PreDecode)
165*09c6f1ddSLingrui98  val (preDecoderIn, preDecoderOut)   = (preDecoder.io.in, preDecoder.io.out)
166*09c6f1ddSLingrui98
167*09c6f1ddSLingrui98  //flush generate and to Ftq
168*09c6f1ddSLingrui98  val predecodeOutValid = WireInit(false.B)
169*09c6f1ddSLingrui98
170*09c6f1ddSLingrui98  when(f1_flush)                  {f1_valid  := false.B}
171*09c6f1ddSLingrui98  .elsewhen(f0_fire && !f0_flush) {f1_valid  := true.B}
172*09c6f1ddSLingrui98  .elsewhen(f1_fire)              {f1_valid  := false.B}
173*09c6f1ddSLingrui98
174*09c6f1ddSLingrui98  toITLB(0).valid         := f1_valid
175*09c6f1ddSLingrui98  toITLB(0).bits.vaddr    := align(f1_ftq_req.startAddr, blockBytes)
176*09c6f1ddSLingrui98  toITLB(0).bits.debug.pc := align(f1_ftq_req.startAddr, blockBytes)
177*09c6f1ddSLingrui98
178*09c6f1ddSLingrui98  toITLB(1).valid         := f1_valid && f1_doubleLine
179*09c6f1ddSLingrui98  toITLB(1).bits.vaddr    := align(f1_ftq_req.fallThruAddr, blockBytes)
180*09c6f1ddSLingrui98  toITLB(1).bits.debug.pc := align(f1_ftq_req.fallThruAddr, blockBytes)
181*09c6f1ddSLingrui98
182*09c6f1ddSLingrui98  toITLB.map{port =>
183*09c6f1ddSLingrui98    port.bits.cmd                 := TlbCmd.exec
184*09c6f1ddSLingrui98    port.bits.roqIdx              := DontCare
185*09c6f1ddSLingrui98    port.bits.debug.isFirstIssue  := DontCare
186*09c6f1ddSLingrui98  }
187*09c6f1ddSLingrui98
188*09c6f1ddSLingrui98  fromITLB.map(_.ready := true.B)
189*09c6f1ddSLingrui98
190*09c6f1ddSLingrui98  val (tlbRespValid, tlbRespPAddr) = (fromITLB.map(_.valid), VecInit(fromITLB.map(_.bits.paddr)))
191*09c6f1ddSLingrui98  val (tlbRespMiss,  tlbRespMMIO)  = (fromITLB.map(port => port.bits.miss && port.valid), fromITLB.map(port => port.bits.mmio && port.valid))
192*09c6f1ddSLingrui98  val (tlbExcpPF,    tlbExcpAF)    = (fromITLB.map(port => port.bits.excp.pf.instr && port.valid), fromITLB.map(port => port.bits.excp.af.instr && port.valid))
193*09c6f1ddSLingrui98
194*09c6f1ddSLingrui98  tlbRespAllValid := tlbRespValid(0)  && (tlbRespValid(1) || !f1_doubleLine)
195*09c6f1ddSLingrui98
196*09c6f1ddSLingrui98  val f1_pAddrs             = tlbRespPAddr   //TODO: Temporary assignment
197*09c6f1ddSLingrui98  val f1_pTags              = VecInit(f1_pAddrs.map(get_tag(_)))
198*09c6f1ddSLingrui98  val (f1_tags, f1_cacheline_valid, f1_datas)   = (meta_resp.tags, meta_resp.valid, data_resp.datas)
199*09c6f1ddSLingrui98  val bank0_hit_vec         = VecInit(f1_tags(0).zipWithIndex.map{ case(way_tag,i) => f1_cacheline_valid(0)(i) && way_tag ===  f1_pTags(0) })
200*09c6f1ddSLingrui98  val bank1_hit_vec         = VecInit(f1_tags(1).zipWithIndex.map{ case(way_tag,i) => f1_cacheline_valid(1)(i) && way_tag ===  f1_pTags(1) })
201*09c6f1ddSLingrui98  val (bank0_hit,bank1_hit) = (ParallelOR(bank0_hit_vec) && !tlbExcpPF(0) && !tlbExcpAF(0), ParallelOR(bank1_hit_vec) && !tlbExcpPF(1) && !tlbExcpAF(1))
202*09c6f1ddSLingrui98  val f1_hit                = (bank0_hit && bank1_hit && f1_valid && f1_doubleLine) || (f1_valid && !f1_doubleLine && bank0_hit)
203*09c6f1ddSLingrui98  val f1_bank_hit_vec       = VecInit(Seq(bank0_hit_vec, bank1_hit_vec))
204*09c6f1ddSLingrui98  val f1_bank_hit           = VecInit(Seq(bank0_hit, bank1_hit))
205*09c6f1ddSLingrui98
206*09c6f1ddSLingrui98  val replacers       = Seq.fill(2)(ReplacementPolicy.fromString(Some("random"),nWays,nSets/2))
207*09c6f1ddSLingrui98  val f1_victim_masks = VecInit(replacers.zipWithIndex.map{case (replacer, i) => UIntToOH(replacer.way(f1_vSetIdx(i)))})
208*09c6f1ddSLingrui98
209*09c6f1ddSLingrui98  val touch_sets = Seq.fill(2)(Wire(Vec(2, UInt(log2Ceil(nSets/2).W))))
210*09c6f1ddSLingrui98  val touch_ways = Seq.fill(2)(Wire(Vec(2, Valid(UInt(log2Ceil(nWays).W)))) )
211*09c6f1ddSLingrui98
212*09c6f1ddSLingrui98  ((replacers zip touch_sets) zip touch_ways).map{case ((r, s),w) => r.access(s,w)}
213*09c6f1ddSLingrui98
214*09c6f1ddSLingrui98  val f1_hit_data      =  VecInit(f1_datas.zipWithIndex.map { case(bank, i) =>
215*09c6f1ddSLingrui98    val bank_hit_data = Mux1H(f1_bank_hit_vec(i).asUInt, bank)
216*09c6f1ddSLingrui98    bank_hit_data
217*09c6f1ddSLingrui98  })
218*09c6f1ddSLingrui98
219*09c6f1ddSLingrui98
220*09c6f1ddSLingrui98  //---------------------------------------------
221*09c6f1ddSLingrui98  //  Fetch Stage 3 :
222*09c6f1ddSLingrui98  //  * get data from last stage (hit from f1_hit_data/miss from missQueue response)
223*09c6f1ddSLingrui98  //  * if at least one needed cacheline miss, wait for miss queue response (a wait_state machine) THIS IS TOO UGLY!!!
224*09c6f1ddSLingrui98  //  * cut cacheline(s) and send to PreDecode
225*09c6f1ddSLingrui98  //  * check if prediction is right (branch target and type, jump direction and type , jal target )
226*09c6f1ddSLingrui98  //---------------------------------------------
227*09c6f1ddSLingrui98  val f2_fetchFinish = Wire(Bool())
228*09c6f1ddSLingrui98
229*09c6f1ddSLingrui98  val f2_valid        = RegInit(false.B)
230*09c6f1ddSLingrui98  val f2_ftq_req      = RegEnable(next = f1_ftq_req,    enable = f1_fire)
231*09c6f1ddSLingrui98  val f2_situation    = RegEnable(next = f1_situation,  enable=f1_fire)
232*09c6f1ddSLingrui98  val f2_doubleLine   = RegEnable(next = f1_doubleLine, enable=f1_fire)
233*09c6f1ddSLingrui98  val f2_fire         = f2_valid && f2_fetchFinish && f3_ready
234*09c6f1ddSLingrui98
235*09c6f1ddSLingrui98  f2_ready := (f3_ready && f2_fetchFinish) || !f2_valid
236*09c6f1ddSLingrui98
237*09c6f1ddSLingrui98  when(f2_flush)                  {f2_valid := false.B}
238*09c6f1ddSLingrui98  .elsewhen(f1_fire && !f1_flush) {f2_valid := true.B }
239*09c6f1ddSLingrui98  .elsewhen(f2_fire)              {f2_valid := false.B}
240*09c6f1ddSLingrui98
241*09c6f1ddSLingrui98
242*09c6f1ddSLingrui98  val f2_pAddrs   = RegEnable(next = f1_pAddrs, enable = f1_fire)
243*09c6f1ddSLingrui98  val f2_hit      = RegEnable(next = f1_hit   , enable = f1_fire)
244*09c6f1ddSLingrui98  val f2_bank_hit = RegEnable(next = f1_bank_hit, enable = f1_fire)
245*09c6f1ddSLingrui98  val f2_miss     = f2_valid && !f2_hit
246*09c6f1ddSLingrui98  val (f2_vSetIdx, f2_pTags) = (RegEnable(next = f1_vSetIdx, enable = f1_fire), RegEnable(next = f1_pTags, enable = f1_fire))
247*09c6f1ddSLingrui98  val f2_waymask  = RegEnable(next = f1_victim_masks, enable = f1_fire)
248*09c6f1ddSLingrui98  //exception information
249*09c6f1ddSLingrui98  val f2_except_pf = RegEnable(next = VecInit(tlbExcpPF), enable = f1_fire)
250*09c6f1ddSLingrui98  val f2_except_af = RegEnable(next = VecInit(tlbExcpAF), enable = f1_fire)
251*09c6f1ddSLingrui98  val f2_except    = VecInit((0 until 2).map{i => f2_except_pf(i) || f2_except_af(i)})
252*09c6f1ddSLingrui98  val f2_has_except = f2_valid && (f2_except_af.reduce(_||_) || f2_except_pf.reduce(_||_))
253*09c6f1ddSLingrui98
254*09c6f1ddSLingrui98  //instruction
255*09c6f1ddSLingrui98  val wait_idle :: wait_queue_ready :: wait_send_req  :: wait_two_resp :: wait_0_resp :: wait_1_resp :: wait_one_resp ::wait_finish :: Nil = Enum(8)
256*09c6f1ddSLingrui98  val wait_state = RegInit(wait_idle)
257*09c6f1ddSLingrui98
258*09c6f1ddSLingrui98  fromMissQueue.map{port => port.ready := true.B}
259*09c6f1ddSLingrui98
260*09c6f1ddSLingrui98  val (miss0_resp, miss1_resp) = (fromMissQueue(0).fire(), fromMissQueue(1).fire())
261*09c6f1ddSLingrui98  val (bank0_fix, bank1_fix)   = (miss0_resp  && !f2_bank_hit(0), miss1_resp && f2_doubleLine && !f2_bank_hit(1))
262*09c6f1ddSLingrui98
263*09c6f1ddSLingrui98  val  only_0_miss = f2_valid && !f2_hit && !f2_doubleLine && !f2_has_except
264*09c6f1ddSLingrui98  val (hit_0_miss_1 ,  miss_0_hit_1,  miss_0_miss_1) = (  (f2_valid && !f2_bank_hit(1) && f2_bank_hit(0) && f2_doubleLine  && !f2_has_except),
265*09c6f1ddSLingrui98                                                          (f2_valid && !f2_bank_hit(0) && f2_bank_hit(1) && f2_doubleLine  && !f2_has_except),
266*09c6f1ddSLingrui98                                                          (f2_valid && !f2_bank_hit(0) && !f2_bank_hit(1) && f2_doubleLine && !f2_has_except),
267*09c6f1ddSLingrui98                                                       )
268*09c6f1ddSLingrui98
269*09c6f1ddSLingrui98  val  hit_0_except_1  = f2_valid && f2_doubleLine &&  !f2_except(0) && f2_except(1)  &&  f2_bank_hit(0)
270*09c6f1ddSLingrui98  val  miss_0_except_1 = f2_valid && f2_doubleLine &&  !f2_except(0) && f2_except(1)  && !f2_bank_hit(0)
271*09c6f1ddSLingrui98  //val  fetch0_except_1 = hit_0_except_1 || miss_0_except_1
272*09c6f1ddSLingrui98  val  except_0        = f2_valid && f2_except(0)
273*09c6f1ddSLingrui98
274*09c6f1ddSLingrui98  val f2_mq_datas     = Reg(Vec(2, UInt(blockBits.W)))
275*09c6f1ddSLingrui98
276*09c6f1ddSLingrui98  when(fromMissQueue(0).fire) {f2_mq_datas(0) :=  fromMissQueue(0).bits.data}
277*09c6f1ddSLingrui98  when(fromMissQueue(1).fire) {f2_mq_datas(1) :=  fromMissQueue(1).bits.data}
278*09c6f1ddSLingrui98
279*09c6f1ddSLingrui98  switch(wait_state){
280*09c6f1ddSLingrui98    is(wait_idle){
281*09c6f1ddSLingrui98      when(miss_0_except_1){
282*09c6f1ddSLingrui98        wait_state :=  Mux(toMissQueue(0).ready, wait_queue_ready ,wait_idle )
283*09c6f1ddSLingrui98      }.elsewhen( only_0_miss  || miss_0_hit_1){
284*09c6f1ddSLingrui98        wait_state :=  Mux(toMissQueue(0).ready, wait_queue_ready ,wait_idle )
285*09c6f1ddSLingrui98      }.elsewhen(hit_0_miss_1){
286*09c6f1ddSLingrui98        wait_state :=  Mux(toMissQueue(1).ready, wait_queue_ready ,wait_idle )
287*09c6f1ddSLingrui98      }.elsewhen( miss_0_miss_1 ){
288*09c6f1ddSLingrui98        wait_state := Mux(toMissQueue(0).ready && toMissQueue(1).ready, wait_queue_ready ,wait_idle)
289*09c6f1ddSLingrui98      }
290*09c6f1ddSLingrui98    }
291*09c6f1ddSLingrui98
292*09c6f1ddSLingrui98    //TODO: naive logic for wait icache response
293*09c6f1ddSLingrui98    is(wait_queue_ready){
294*09c6f1ddSLingrui98      wait_state := wait_send_req
295*09c6f1ddSLingrui98    }
296*09c6f1ddSLingrui98
297*09c6f1ddSLingrui98    is(wait_send_req) {
298*09c6f1ddSLingrui98      when(miss_0_except_1 || only_0_miss || hit_0_miss_1 || miss_0_hit_1){
299*09c6f1ddSLingrui98        wait_state :=  wait_one_resp
300*09c6f1ddSLingrui98      }.elsewhen( miss_0_miss_1 ){
301*09c6f1ddSLingrui98        wait_state := wait_two_resp
302*09c6f1ddSLingrui98      }
303*09c6f1ddSLingrui98    }
304*09c6f1ddSLingrui98
305*09c6f1ddSLingrui98    is(wait_one_resp) {
306*09c6f1ddSLingrui98      when( (miss_0_except_1 ||only_0_miss || miss_0_hit_1) && fromMissQueue(0).fire()){
307*09c6f1ddSLingrui98        wait_state := wait_finish
308*09c6f1ddSLingrui98      }.elsewhen( hit_0_miss_1 && fromMissQueue(1).fire()){
309*09c6f1ddSLingrui98        wait_state := wait_finish
310*09c6f1ddSLingrui98      }
311*09c6f1ddSLingrui98    }
312*09c6f1ddSLingrui98
313*09c6f1ddSLingrui98    is(wait_two_resp) {
314*09c6f1ddSLingrui98      when(fromMissQueue(0).fire() && fromMissQueue(1).fire()){
315*09c6f1ddSLingrui98        wait_state := wait_finish
316*09c6f1ddSLingrui98      }.elsewhen( !fromMissQueue(0).fire() && fromMissQueue(1).fire() ){
317*09c6f1ddSLingrui98        wait_state := wait_0_resp
318*09c6f1ddSLingrui98      }.elsewhen(fromMissQueue(0).fire() && !fromMissQueue(1).fire()){
319*09c6f1ddSLingrui98        wait_state := wait_1_resp
320*09c6f1ddSLingrui98      }
321*09c6f1ddSLingrui98    }
322*09c6f1ddSLingrui98
323*09c6f1ddSLingrui98    is(wait_0_resp) {
324*09c6f1ddSLingrui98      when(fromMissQueue(0).fire()){
325*09c6f1ddSLingrui98        wait_state := wait_finish
326*09c6f1ddSLingrui98      }
327*09c6f1ddSLingrui98    }
328*09c6f1ddSLingrui98
329*09c6f1ddSLingrui98    is(wait_1_resp) {
330*09c6f1ddSLingrui98      when(fromMissQueue(1).fire()){
331*09c6f1ddSLingrui98        wait_state := wait_finish
332*09c6f1ddSLingrui98      }
333*09c6f1ddSLingrui98    }
334*09c6f1ddSLingrui98
335*09c6f1ddSLingrui98    is(wait_finish) {
336*09c6f1ddSLingrui98      when(f2_fire) {wait_state := wait_idle }
337*09c6f1ddSLingrui98    }
338*09c6f1ddSLingrui98  }
339*09c6f1ddSLingrui98
340*09c6f1ddSLingrui98  when(f2_flush) { wait_state := wait_idle }
341*09c6f1ddSLingrui98
342*09c6f1ddSLingrui98  (0 until 2).map { i =>
343*09c6f1ddSLingrui98    if(i == 1) toMissQueue(i).valid := (hit_0_miss_1 || miss_0_miss_1) && wait_state === wait_queue_ready
344*09c6f1ddSLingrui98      else     toMissQueue(i).valid := (only_0_miss || miss_0_hit_1 || miss_0_miss_1) && wait_state === wait_queue_ready
345*09c6f1ddSLingrui98    toMissQueue(i).bits.addr    := f2_pAddrs(i)
346*09c6f1ddSLingrui98    toMissQueue(i).bits.vSetIdx := f2_vSetIdx(i)
347*09c6f1ddSLingrui98    toMissQueue(i).bits.waymask := f2_waymask(i)
348*09c6f1ddSLingrui98    toMissQueue(i).bits.clientID :=0.U
349*09c6f1ddSLingrui98  }
350*09c6f1ddSLingrui98
351*09c6f1ddSLingrui98  val miss_all_fix       = (wait_state === wait_finish)
352*09c6f1ddSLingrui98
353*09c6f1ddSLingrui98  f2_fetchFinish         := ((f2_valid && f2_hit) || miss_all_fix || hit_0_except_1 || except_0)
354*09c6f1ddSLingrui98
355*09c6f1ddSLingrui98
356*09c6f1ddSLingrui98  (touch_ways zip touch_sets).zipWithIndex.map{ case((t_w,t_s), i) =>
357*09c6f1ddSLingrui98    t_s(0)         := f1_vSetIdx(i)
358*09c6f1ddSLingrui98    t_w(0).valid   := f1_bank_hit(i)
359*09c6f1ddSLingrui98    t_w(0).bits    := OHToUInt(f1_bank_hit_vec(i))
360*09c6f1ddSLingrui98
361*09c6f1ddSLingrui98    t_s(1)         := f2_vSetIdx(i)
362*09c6f1ddSLingrui98    t_w(1).valid   := f2_valid && !f2_bank_hit(i)
363*09c6f1ddSLingrui98    t_w(1).bits    := OHToUInt(f2_waymask(i))
364*09c6f1ddSLingrui98  }
365*09c6f1ddSLingrui98
366*09c6f1ddSLingrui98  val sec_miss_reg   = RegInit(0.U.asTypeOf(Vec(4, Bool())))
367*09c6f1ddSLingrui98  val reservedRefillData = Reg(Vec(2, UInt(blockBits.W)))
368*09c6f1ddSLingrui98  val f2_hit_datas    = RegEnable(next = f1_hit_data, enable = f1_fire)
369*09c6f1ddSLingrui98  val f2_datas        = Wire(Vec(2, UInt(blockBits.W)))
370*09c6f1ddSLingrui98
371*09c6f1ddSLingrui98  f2_datas.zipWithIndex.map{case(bank,i) =>
372*09c6f1ddSLingrui98    if(i == 0) bank := Mux(f2_bank_hit(i), f2_hit_datas(i),Mux(sec_miss_reg(2),reservedRefillData(1),Mux(sec_miss_reg(0),reservedRefillData(0), f2_mq_datas(i))))
373*09c6f1ddSLingrui98    else bank := Mux(f2_bank_hit(i), f2_hit_datas(i),Mux(sec_miss_reg(3),reservedRefillData(1),Mux(sec_miss_reg(1),reservedRefillData(0), f2_mq_datas(i))))
374*09c6f1ddSLingrui98  }
375*09c6f1ddSLingrui98
376*09c6f1ddSLingrui98  val f2_jump_valids          = Fill(PredictWidth, !preDecoderOut.cfiOffset.valid)   | Fill(PredictWidth, 1.U(1.W)) >> (~preDecoderOut.cfiOffset.bits)
377*09c6f1ddSLingrui98  val f2_predecode_valids     = VecInit(preDecoderOut.pd.map(instr => instr.valid)).asUInt & f2_jump_valids
378*09c6f1ddSLingrui98
379*09c6f1ddSLingrui98  def cut(cacheline: UInt, start: UInt) : Vec[UInt] ={
380*09c6f1ddSLingrui98    if(HasCExtension){
381*09c6f1ddSLingrui98      val result   = Wire(Vec(PredictWidth + 1, UInt(16.W)))
382*09c6f1ddSLingrui98      val dataVec  = cacheline.asTypeOf(Vec(blockBytes * 2/ 2, UInt(16.W)))
383*09c6f1ddSLingrui98      val startPtr = Cat(0.U(1.W), start(blockOffBits-1, 1))
384*09c6f1ddSLingrui98      (0 until PredictWidth + 1).foreach( i =>
385*09c6f1ddSLingrui98        result(i) := dataVec(startPtr + i.U)
386*09c6f1ddSLingrui98      )
387*09c6f1ddSLingrui98      result
388*09c6f1ddSLingrui98    } else {
389*09c6f1ddSLingrui98      val result   = Wire(Vec(PredictWidth, UInt(32.W)) )
390*09c6f1ddSLingrui98      val dataVec  = cacheline.asTypeOf(Vec(blockBytes * 2/ 4, UInt(32.W)))
391*09c6f1ddSLingrui98      val startPtr = Cat(0.U(1.W), start(blockOffBits-1, 2))
392*09c6f1ddSLingrui98      (0 until PredictWidth).foreach( i =>
393*09c6f1ddSLingrui98        result(i) := dataVec(startPtr + i.U)
394*09c6f1ddSLingrui98      )
395*09c6f1ddSLingrui98      result
396*09c6f1ddSLingrui98    }
397*09c6f1ddSLingrui98  }
398*09c6f1ddSLingrui98
399*09c6f1ddSLingrui98  val f2_cut_data = cut( Cat(f2_datas.map(cacheline => cacheline.asUInt ).reverse).asUInt, f2_ftq_req.startAddr )
400*09c6f1ddSLingrui98
401*09c6f1ddSLingrui98  // deal with secondary miss in f1
402*09c6f1ddSLingrui98  val f2_0_f1_0 =   ((f2_valid && !f2_bank_hit(0)) && f1_valid && (get_block_addr(f2_ftq_req.startAddr) === get_block_addr(f1_ftq_req.startAddr)))
403*09c6f1ddSLingrui98  val f2_0_f1_1 =   ((f2_valid && !f2_bank_hit(0)) && f1_valid && f1_doubleLine && (get_block_addr(f2_ftq_req.startAddr) === get_block_addr(f1_ftq_req.startAddr + blockBytes.U)))
404*09c6f1ddSLingrui98  val f2_1_f1_0 =   ((f2_valid && !f2_bank_hit(1) && f2_doubleLine) && f1_valid && (get_block_addr(f2_ftq_req.startAddr+ blockBytes.U) === get_block_addr(f1_ftq_req.startAddr) ))
405*09c6f1ddSLingrui98  val f2_1_f1_1 =   ((f2_valid && !f2_bank_hit(1) && f2_doubleLine) && f1_valid && f1_doubleLine && (get_block_addr(f2_ftq_req.startAddr+ blockBytes.U) === get_block_addr(f1_ftq_req.startAddr + blockBytes.U) ))
406*09c6f1ddSLingrui98
407*09c6f1ddSLingrui98  val isSameLine = f2_0_f1_0 || f2_0_f1_1 || f2_1_f1_0 || f2_1_f1_1
408*09c6f1ddSLingrui98  val sec_miss_sit   = VecInit(Seq(f2_0_f1_0, f2_0_f1_1, f2_1_f1_0, f2_1_f1_1))
409*09c6f1ddSLingrui98  val hasSecMiss     = RegInit(false.B)
410*09c6f1ddSLingrui98
411*09c6f1ddSLingrui98  when(f2_flush){
412*09c6f1ddSLingrui98    sec_miss_reg.map(sig => sig := false.B)
413*09c6f1ddSLingrui98    hasSecMiss := false.B
414*09c6f1ddSLingrui98  }.elsewhen(isSameLine && !f1_flush && f2_fire){
415*09c6f1ddSLingrui98    sec_miss_reg.zipWithIndex.map{case(sig, i) => sig := sec_miss_sit(i)}
416*09c6f1ddSLingrui98    hasSecMiss := true.B
417*09c6f1ddSLingrui98  }.elsewhen((!isSameLine || f1_flush) && hasSecMiss && f2_fire){
418*09c6f1ddSLingrui98    sec_miss_reg.map(sig => sig := false.B)
419*09c6f1ddSLingrui98    hasSecMiss := false.B
420*09c6f1ddSLingrui98  }
421*09c6f1ddSLingrui98
422*09c6f1ddSLingrui98  when((f2_0_f1_0 || f2_0_f1_1) && f2_fire){
423*09c6f1ddSLingrui98    reservedRefillData(0) := f2_mq_datas(0)
424*09c6f1ddSLingrui98  }
425*09c6f1ddSLingrui98
426*09c6f1ddSLingrui98  when((f2_1_f1_0 || f2_1_f1_1) && f2_fire){
427*09c6f1ddSLingrui98    reservedRefillData(1) := f2_mq_datas(1)
428*09c6f1ddSLingrui98  }
429*09c6f1ddSLingrui98
430*09c6f1ddSLingrui98
431*09c6f1ddSLingrui98  //---------------------------------------------
432*09c6f1ddSLingrui98  //  Fetch Stage 4 :
433*09c6f1ddSLingrui98  //  * get data from last stage (hit from f1_hit_data/miss from missQueue response)
434*09c6f1ddSLingrui98  //  * if at least one needed cacheline miss, wait for miss queue response (a wait_state machine) THIS IS TOO UGLY!!!
435*09c6f1ddSLingrui98  //  * cut cacheline(s) and send to PreDecode
436*09c6f1ddSLingrui98  //  * check if prediction is right (branch target and type, jump direction and type , jal target )
437*09c6f1ddSLingrui98  //---------------------------------------------
438*09c6f1ddSLingrui98  val f3_valid          = RegInit(false.B)
439*09c6f1ddSLingrui98  val f3_ftq_req        = RegEnable(next = f2_ftq_req,    enable=f2_fire)
440*09c6f1ddSLingrui98  val f3_situation      = RegEnable(next = f2_situation,  enable=f2_fire)
441*09c6f1ddSLingrui98  val f3_doubleLine     = RegEnable(next = f2_doubleLine, enable=f2_fire)
442*09c6f1ddSLingrui98  val f3_fire           = io.toIbuffer.fire()
443*09c6f1ddSLingrui98
444*09c6f1ddSLingrui98  when(f3_flush)                  {f3_valid := false.B}
445*09c6f1ddSLingrui98  .elsewhen(f2_fire && !f2_flush) {f3_valid := true.B }
446*09c6f1ddSLingrui98  .elsewhen(io.toIbuffer.fire())  {f3_valid := false.B}
447*09c6f1ddSLingrui98
448*09c6f1ddSLingrui98  f3_ready := io.toIbuffer.ready || !f2_valid
449*09c6f1ddSLingrui98
450*09c6f1ddSLingrui98  val f3_cut_data       = RegEnable(next = f2_cut_data, enable=f2_fire)
451*09c6f1ddSLingrui98  val f3_except_pf      = RegEnable(next = f2_except_pf, enable = f2_fire)
452*09c6f1ddSLingrui98  val f3_except_af      = RegEnable(next = f2_except_af, enable = f2_fire)
453*09c6f1ddSLingrui98  val f3_hit            = RegEnable(next = f2_hit   , enable = f2_fire)
454*09c6f1ddSLingrui98
455*09c6f1ddSLingrui98  val f3_lastHalf       = RegInit(0.U.asTypeOf(new LastHalfInfo))
456*09c6f1ddSLingrui98  val f3_lastHalfMatch  = f3_lastHalf.matchThisBlock(f3_ftq_req.startAddr)
457*09c6f1ddSLingrui98  val f3_except         = VecInit((0 until 2).map{i => f3_except_pf(i) || f3_except_af(i)})
458*09c6f1ddSLingrui98  val f3_has_except     = f3_valid && (f3_except_af.reduce(_||_) || f3_except_pf.reduce(_||_))
459*09c6f1ddSLingrui98
460*09c6f1ddSLingrui98
461*09c6f1ddSLingrui98  preDecoderIn.instValid     :=  f3_valid && !f3_has_except
462*09c6f1ddSLingrui98  preDecoderIn.data          :=  f3_cut_data
463*09c6f1ddSLingrui98  preDecoderIn.startAddr     :=  f3_ftq_req.startAddr
464*09c6f1ddSLingrui98  preDecoderIn.fallThruAddr  :=  f3_ftq_req.fallThruAddr
465*09c6f1ddSLingrui98  preDecoderIn.fallThruError :=  f3_ftq_req.fallThruError
466*09c6f1ddSLingrui98  preDecoderIn.isDoubleLine  :=  f3_doubleLine
467*09c6f1ddSLingrui98  preDecoderIn.ftqOffset     :=  f3_ftq_req.ftqOffset
468*09c6f1ddSLingrui98  preDecoderIn.target        :=  f3_ftq_req.target
469*09c6f1ddSLingrui98  preDecoderIn.oversize      :=  f3_ftq_req.oversize
470*09c6f1ddSLingrui98  preDecoderIn.lastHalfMatch :=  f3_lastHalfMatch
471*09c6f1ddSLingrui98  preDecoderIn.pageFault     :=  f3_except_pf
472*09c6f1ddSLingrui98  preDecoderIn.accessFault   :=  f3_except_af
473*09c6f1ddSLingrui98
474*09c6f1ddSLingrui98
475*09c6f1ddSLingrui98  // TODO: What if next packet does not match?
476*09c6f1ddSLingrui98  when (f3_flush) {
477*09c6f1ddSLingrui98    f3_lastHalf.valid := false.B
478*09c6f1ddSLingrui98  }.elsewhen (io.toIbuffer.fire()) {
479*09c6f1ddSLingrui98    f3_lastHalf.valid := preDecoderOut.hasLastHalf
480*09c6f1ddSLingrui98    f3_lastHalf.middlePC := preDecoderOut.realEndPC
481*09c6f1ddSLingrui98  }
482*09c6f1ddSLingrui98
483*09c6f1ddSLingrui98  val f3_predecode_range = VecInit(preDecoderOut.pd.map(inst => inst.valid)).asUInt
484*09c6f1ddSLingrui98
485*09c6f1ddSLingrui98  io.toIbuffer.valid          := f3_valid
486*09c6f1ddSLingrui98  io.toIbuffer.bits.instrs    := preDecoderOut.instrs
487*09c6f1ddSLingrui98  io.toIbuffer.bits.valid     := f3_predecode_range & preDecoderOut.instrRange.asUInt
488*09c6f1ddSLingrui98  io.toIbuffer.bits.pd        := preDecoderOut.pd
489*09c6f1ddSLingrui98  io.toIbuffer.bits.ftqPtr    := f3_ftq_req.ftqIdx
490*09c6f1ddSLingrui98  io.toIbuffer.bits.pc        := preDecoderOut.pc
491*09c6f1ddSLingrui98  io.toIbuffer.bits.ftqOffset.zipWithIndex.map{case(a, i) => a.bits := i.U; a.valid := preDecoderOut.takens(i)}
492*09c6f1ddSLingrui98  io.toIbuffer.bits.foldpc    := preDecoderOut.pc.map(i => XORFold(i(VAddrBits-1,1), MemPredPCWidth))
493*09c6f1ddSLingrui98  io.toIbuffer.bits.ipf       := preDecoderOut.pageFault
494*09c6f1ddSLingrui98  io.toIbuffer.bits.acf       := preDecoderOut.accessFault
495*09c6f1ddSLingrui98  io.toIbuffer.bits.crossPageIPFFix := preDecoderOut.crossPageIPF
496*09c6f1ddSLingrui98
497*09c6f1ddSLingrui98  //Write back to Ftq
498*09c6f1ddSLingrui98  val finishFetchMaskReg = RegNext(f3_valid && !(f2_fire && !f2_flush))
499*09c6f1ddSLingrui98
500*09c6f1ddSLingrui98  toFtq.pdWb.valid           := !finishFetchMaskReg && f3_valid
501*09c6f1ddSLingrui98  toFtq.pdWb.bits.pc         := preDecoderOut.pc
502*09c6f1ddSLingrui98  toFtq.pdWb.bits.pd         := preDecoderOut.pd
503*09c6f1ddSLingrui98  toFtq.pdWb.bits.pd.zipWithIndex.map{case(instr,i) => instr.valid :=  f3_predecode_range(i)}
504*09c6f1ddSLingrui98  toFtq.pdWb.bits.ftqIdx     := f3_ftq_req.ftqIdx
505*09c6f1ddSLingrui98  toFtq.pdWb.bits.ftqOffset  := f3_ftq_req.ftqOffset.bits
506*09c6f1ddSLingrui98  toFtq.pdWb.bits.misOffset  := preDecoderOut.misOffset
507*09c6f1ddSLingrui98  toFtq.pdWb.bits.cfiOffset  := preDecoderOut.cfiOffset
508*09c6f1ddSLingrui98  toFtq.pdWb.bits.target     := preDecoderOut.target
509*09c6f1ddSLingrui98  toFtq.pdWb.bits.jalTarget  := preDecoderOut.jalTarget
510*09c6f1ddSLingrui98  toFtq.pdWb.bits.instrRange := preDecoderOut.instrRange
511*09c6f1ddSLingrui98
512*09c6f1ddSLingrui98  val predecodeFlush     = preDecoderOut.misOffset.valid && f3_valid
513*09c6f1ddSLingrui98  val predecodeFlushReg  = RegNext(predecodeFlush && !(f2_fire && !f2_flush))
514*09c6f1ddSLingrui98
515*09c6f1ddSLingrui98  f3_redirect := !predecodeFlushReg && predecodeFlush
516*09c6f1ddSLingrui98
517*09c6f1ddSLingrui98  // Performance Counter
518*09c6f1ddSLingrui98  XSPerfAccumulate("req",   io.toIbuffer.fire() )
519*09c6f1ddSLingrui98  XSPerfAccumulate("miss",  io.toIbuffer.fire() && !f3_hit )
520*09c6f1ddSLingrui98  XSPerfAccumulate("frontendFlush",  f3_redirect )
521*09c6f1ddSLingrui98  XSPerfAccumulate("only_0_miss",   only_0_miss )
522*09c6f1ddSLingrui98  XSPerfAccumulate("hit_0_miss_1",  hit_0_miss_1 )
523*09c6f1ddSLingrui98  XSPerfAccumulate("miss_0_hit_1",  miss_0_hit_1 )
524*09c6f1ddSLingrui98  XSPerfAccumulate("miss_0_miss_1", miss_0_miss_1 )
525*09c6f1ddSLingrui98  XSPerfAccumulate("crossLine", io.toIbuffer.fire() && f3_situation(0) )
526*09c6f1ddSLingrui98  XSPerfAccumulate("lastInLin", io.toIbuffer.fire() && f3_situation(1) )
527*09c6f1ddSLingrui98}
528