CtrlBlock.scala 17.5 KB
Newer Older
L
Lemover 已提交
1 2
/***************************************************************************************
* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
Y
Yinan Xu 已提交
3
* Copyright (c) 2020-2021 Peng Cheng Laboratory
L
Lemover 已提交
4 5 6 7 8 9 10 11 12 13 14 15 16
*
* XiangShan is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*          http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
***************************************************************************************/

17 18
package xiangshan.backend

19
import chipsalliance.rocketchip.config.Parameters
20 21
import chisel3._
import chisel3.util._
Y
Yinan Xu 已提交
22
import utils._
23
import xiangshan._
24
import xiangshan.backend.decode.{DecodeStage, ImmUnion}
25
import xiangshan.backend.dispatch.{Dispatch, DispatchQueue}
26
import xiangshan.backend.rename.{Rename, RenameTableWrapper}
27
import xiangshan.backend.rob.{Rob, RobCSRIO, RobLsqIO}
28
import xiangshan.backend.fu.{PFEvent}
29
import xiangshan.frontend.{FtqPtr, FtqRead}
Y
Yinan Xu 已提交
30
import xiangshan.mem.LsqEnqIO
W
William Wang 已提交
31
import difftest._
32

33
class CtrlToFtqIO(implicit p: Parameters) extends XSBundle {
Y
Yinan Xu 已提交
34
  val rob_commits = Vec(CommitWidth, Valid(new RobCommitInfo))
35
  val stage2Redirect = Valid(new Redirect)
L
Lingrui98 已提交
36
  val stage3Redirect = ValidIO(new Redirect)
37
  val robFlush = ValidIO(new Redirect)
38 39
}

40
class RedirectGenerator(implicit p: Parameters) extends XSModule
41
  with HasCircularQueuePtrHelper {
L
ljw 已提交
42
  val numRedirect = exuParameters.JmpCnt + exuParameters.AluCnt
L
LinJiawei 已提交
43
  val io = IO(new Bundle() {
J
Jiawei Lin 已提交
44
    val hartId = Input(UInt(8.W))
L
ljw 已提交
45
    val exuMispredict = Vec(numRedirect, Flipped(ValidIO(new ExuOutput)))
L
ljw 已提交
46
    val loadReplay = Flipped(ValidIO(new Redirect))
47
    val flush = Input(Bool())
Z
zoujr 已提交
48
    val stage1PcRead = Vec(numRedirect+1, new FtqRead(UInt(VAddrBits.W)))
L
LinJiawei 已提交
49
    val stage2Redirect = ValidIO(new Redirect)
L
LinJiawei 已提交
50
    val stage3Redirect = ValidIO(new Redirect)
51
    val memPredUpdate = Output(new MemPredUpdateReq)
Z
zoujr 已提交
52
    val memPredPcRead = new FtqRead(UInt(VAddrBits.W)) // read req send form stage 2
L
LinJiawei 已提交
53 54 55 56
  })
  /*
        LoadQueue  Jump  ALU0  ALU1  ALU2  ALU3   exception    Stage1
          |         |      |    |     |     |         |
L
LinJiawei 已提交
57
          |============= reg & compare =====|         |       ========
L
LinJiawei 已提交
58 59 60 61
                            |                         |
                            |                         |
                            |                         |        Stage2
                            |                         |
L
LinJiawei 已提交
62 63 64 65 66 67 68 69
                    redirect (flush backend)          |
                    |                                 |
               === reg ===                            |       ========
                    |                                 |
                    |----- mux (exception first) -----|        Stage3
                            |
                redirect (send to frontend)
   */
L
ljw 已提交
70 71 72 73
  private class Wrapper(val n: Int) extends Bundle {
    val redirect = new Redirect
    val valid = Bool()
    val idx = UInt(log2Up(n).W)
74
  }
75
  def selectOldestRedirect(xs: Seq[Valid[Redirect]]): Vec[Bool] = {
Y
Yinan Xu 已提交
76
    val compareVec = (0 until xs.length).map(i => (0 until i).map(j => isAfter(xs(j).bits.robIdx, xs(i).bits.robIdx)))
77 78 79 80 81 82
    val resultOnehot = VecInit((0 until xs.length).map(i => Cat((0 until xs.length).map(j =>
      (if (j < i) !xs(j).valid || compareVec(i)(j)
      else if (j == i) xs(i).valid
      else !xs(j).valid || !compareVec(j)(i))
    )).andR))
    resultOnehot
L
LinJiawei 已提交
83 84
  }

85
  val redirects = io.exuMispredict.map(_.bits.redirect) :+ io.loadReplay.bits
Y
Yinan Xu 已提交
86 87
  val stage1FtqReadPcs =
    (io.stage1PcRead zip redirects).map{ case (r, redirect) =>
88 89
      r(redirect.ftqIdx, redirect.ftqOffset)
    }
L
ljw 已提交
90 91

  def getRedirect(exuOut: Valid[ExuOutput]): ValidIO[Redirect] = {
L
LinJiawei 已提交
92
    val redirect = Wire(Valid(new Redirect))
L
ljw 已提交
93 94
    redirect.valid := exuOut.valid && exuOut.bits.redirect.cfiUpdate.isMisPred
    redirect.bits := exuOut.bits.redirect
L
LinJiawei 已提交
95
    redirect
L
ljw 已提交
96
  }
L
LinJiawei 已提交
97

L
ljw 已提交
98
  val jumpOut = io.exuMispredict.head
99 100
  val allRedirect = VecInit(io.exuMispredict.map(x => getRedirect(x)) :+ io.loadReplay)
  val oldestOneHot = selectOldestRedirect(allRedirect)
101
  val needFlushVec = VecInit(allRedirect.map(_.bits.robIdx.needFlush(io.stage2Redirect) || io.flush))
102
  val oldestValid = VecInit(oldestOneHot.zip(needFlushVec).map{ case (v, f) => v && !f }).asUInt.orR
103
  val oldestExuOutput = Mux1H(io.exuMispredict.indices.map(oldestOneHot), io.exuMispredict)
104
  val oldestRedirect = Mux1H(oldestOneHot, allRedirect)
105

L
LinJiawei 已提交
106
  val s1_jumpTarget = RegEnable(jumpOut.bits.redirect.cfiUpdate.target, jumpOut.valid)
107 108 109 110 111
  val s1_imm12_reg = RegNext(oldestExuOutput.bits.uop.ctrl.imm(11, 0))
  val s1_pd = RegNext(oldestExuOutput.bits.uop.cf.pd)
  val s1_redirect_bits_reg = RegNext(oldestRedirect.bits)
  val s1_redirect_valid_reg = RegNext(oldestValid)
  val s1_redirect_onehot = RegNext(oldestOneHot)
L
LinJiawei 已提交
112 113

  // stage1 -> stage2
114
  io.stage2Redirect.valid := s1_redirect_valid_reg && !io.flush
L
LinJiawei 已提交
115 116 117
  io.stage2Redirect.bits := s1_redirect_bits_reg
  io.stage2Redirect.bits.cfiUpdate := DontCare

118 119
  val s1_isReplay = s1_redirect_onehot.last
  val s1_isJump = s1_redirect_onehot.head
120
  val real_pc = Mux1H(s1_redirect_onehot, stage1FtqReadPcs)
L
ljw 已提交
121 122
  val brTarget = real_pc + SignExt(ImmUnion.B.toImm32(s1_imm12_reg), XLEN)
  val snpc = real_pc + Mux(s1_pd.isRVC, 2.U, 4.U)
123
  val target = Mux(s1_isReplay,
124
    real_pc, // replay from itself
L
ljw 已提交
125 126
    Mux(s1_redirect_bits_reg.cfiUpdate.taken,
      Mux(s1_isJump, s1_jumpTarget, brTarget),
L
LinJiawei 已提交
127
      snpc
L
LinJiawei 已提交
128 129
    )
  )
130

131 132 133
  // get pc from ftq
  // valid only if redirect is caused by load violation
  // store_pc is used to update store set
134
  val store_pc = io.memPredPcRead(s1_redirect_bits_reg.stFtqIdx, s1_redirect_bits_reg.stFtqOffset)
135 136 137 138 139 140 141 142 143 144

  // update load violation predictor if load violation redirect triggered
  io.memPredUpdate.valid := RegNext(s1_isReplay && s1_redirect_valid_reg, init = false.B)
  // update wait table
  io.memPredUpdate.waddr := RegNext(XORFold(real_pc(VAddrBits-1, 1), MemPredPCWidth))
  io.memPredUpdate.wdata := true.B
  // update store set
  io.memPredUpdate.ldpc := RegNext(XORFold(real_pc(VAddrBits-1, 1), MemPredPCWidth))
  // store pc is ready 1 cycle after s1_isReplay is judged
  io.memPredUpdate.stpc := XORFold(store_pc(VAddrBits-1, 1), MemPredPCWidth)
145

L
ljw 已提交
146 147
  val s2_target = RegEnable(target, enable = s1_redirect_valid_reg)
  val s2_pd = RegEnable(s1_pd, enable = s1_redirect_valid_reg)
148
  val s2_pc = RegEnable(real_pc, enable = s1_redirect_valid_reg)
L
ljw 已提交
149 150 151
  val s2_redirect_bits_reg = RegEnable(s1_redirect_bits_reg, enable = s1_redirect_valid_reg)
  val s2_redirect_valid_reg = RegNext(s1_redirect_valid_reg && !io.flush, init = false.B)

L
LinJiawei 已提交
152 153 154
  io.stage3Redirect.valid := s2_redirect_valid_reg
  io.stage3Redirect.bits := s2_redirect_bits_reg
  val stage3CfiUpdate = io.stage3Redirect.bits.cfiUpdate
155
  stage3CfiUpdate.pc := s2_pc
L
LinJiawei 已提交
156
  stage3CfiUpdate.pd := s2_pd
L
LinJiawei 已提交
157
  stage3CfiUpdate.predTaken := s2_redirect_bits_reg.cfiUpdate.predTaken
L
ljw 已提交
158
  stage3CfiUpdate.target := s2_target
L
LinJiawei 已提交
159 160
  stage3CfiUpdate.taken := s2_redirect_bits_reg.cfiUpdate.taken
  stage3CfiUpdate.isMisPred := s2_redirect_bits_reg.cfiUpdate.isMisPred
W
William Wang 已提交
161 162 163 164 165

  // recover runahead checkpoint if redirect
  if (!env.FPGAPlatform) {
    val runahead_redirect = Module(new DifftestRunaheadRedirectEvent)
    runahead_redirect.io.clock := clock
J
Jiawei Lin 已提交
166
    runahead_redirect.io.coreid := io.hartId
W
William Wang 已提交
167 168 169 170 171
    runahead_redirect.io.valid := io.stage3Redirect.valid
    runahead_redirect.io.pc :=  s2_pc // for debug only
    runahead_redirect.io.target_pc := s2_target // for debug only
    runahead_redirect.io.checkpoint_id := io.stage3Redirect.bits.debug_runahead_checkpoint_id // make sure it is right
  }
L
LinJiawei 已提交
172 173
}

174
class CtrlBlock(implicit p: Parameters) extends XSModule
175
  with HasCircularQueuePtrHelper {
176
  val io = IO(new Bundle {
J
Jiawei Lin 已提交
177
    val hartId = Input(UInt(8.W))
178
    val frontend = Flipped(new FrontendToCtrlIO)
179 180
    val allocPregs = Vec(RenameWidth, Output(new ResetPregStateReq))
    val dispatch = Vec(3*dpParams.IntDqDeqWidth, DecoupledIO(new MicroOp))
181 182 183 184 185 186 187
    // from int block
    val exuRedirect = Vec(exuParameters.AluCnt + exuParameters.JmpCnt, Flipped(ValidIO(new ExuOutput)))
    val stIn = Vec(exuParameters.StuCnt, Flipped(ValidIO(new ExuInput)))
    val stOut = Vec(exuParameters.StuCnt, Flipped(ValidIO(new ExuOutput)))
    val memoryViolation = Flipped(ValidIO(new Redirect))
    val jumpPc = Output(UInt(VAddrBits.W))
    val jalr_target = Output(UInt(VAddrBits.W))
Y
Yinan Xu 已提交
188
    val robio = new Bundle {
Y
Yinan Xu 已提交
189
      // to int block
Y
Yinan Xu 已提交
190
      val toCSR = new RobCSRIO
191
      val exception = ValidIO(new ExceptionInfo)
Y
Yinan Xu 已提交
192
      // to mem block
Y
Yinan Xu 已提交
193
      val lsq = new RobLsqIO
Y
Yinan Xu 已提交
194
    }
195
    val csrCtrl = Input(new CustomCSRCtrlIO)
196 197
    val perfInfo = Output(new Bundle{
      val ctrlInfo = new Bundle {
Y
Yinan Xu 已提交
198
        val robFull   = Input(Bool())
199 200 201 202 203
        val intdqFull = Input(Bool())
        val fpdqFull  = Input(Bool())
        val lsdqFull  = Input(Bool())
      }
    })
204
    val writeback = Vec(NRIntWritePorts + NRFpWritePorts, Flipped(ValidIO(new ExuOutput)))
205 206 207 208
    // redirect out
    val redirect = ValidIO(new Redirect)
    val debug_int_rat = Vec(32, Output(UInt(PhyRegIdxWidth.W)))
    val debug_fp_rat = Vec(32, Output(UInt(PhyRegIdxWidth.W)))
209 210 211
  })

  val decode = Module(new DecodeStage)
212
  val rat = Module(new RenameTableWrapper)
213
  val rename = Module(new Rename)
214
  val dispatch = Module(new Dispatch)
215 216 217
  val intDq = Module(new DispatchQueue(dpParams.IntDqSize, RenameWidth, dpParams.IntDqDeqWidth, "int"))
  val fpDq = Module(new DispatchQueue(dpParams.FpDqSize, RenameWidth, dpParams.FpDqDeqWidth, "fp"))
  val lsDq = Module(new DispatchQueue(dpParams.LsDqSize, RenameWidth, dpParams.LsDqDeqWidth, "ls"))
L
LinJiawei 已提交
218
  val redirectGen = Module(new RedirectGenerator)
219

Y
Yinan Xu 已提交
220 221
  val robWbSize = NRIntWritePorts + NRFpWritePorts + exuParameters.StuCnt
  val rob = Module(new Rob(robWbSize))
222

223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
  val robPcRead = io.frontend.fromFtq.getRobFlushPcRead
  val flushPC = robPcRead(rob.io.flushOut.bits.ftqIdx, rob.io.flushOut.bits.ftqOffset)

  val flushRedirect = Wire(Valid(new Redirect))
  flushRedirect.valid := RegNext(rob.io.flushOut.valid)
  flushRedirect.bits := RegEnable(rob.io.flushOut.bits, rob.io.flushOut.valid)
  flushRedirect.bits.cfiUpdate.target := Mux(io.robio.toCSR.isXRet || rob.io.exception.valid,
    io.robio.toCSR.trapTarget,
    Mux(flushRedirect.bits.flushItself(),
      flushPC, // replay inst
      flushPC + 4.U // flush pipe
    )
  )

  val flushRedirectReg = Wire(Valid(new Redirect))
  flushRedirectReg.valid := RegNext(flushRedirect.valid, init = false.B)
  flushRedirectReg.bits := RegEnable(flushRedirect.bits, enable = flushRedirect.valid)

  val stage2Redirect = Mux(flushRedirect.valid, flushRedirect, redirectGen.io.stage2Redirect)
  val stage3Redirect = Mux(flushRedirectReg.valid, flushRedirectReg, redirectGen.io.stage3Redirect)
L
LinJiawei 已提交
243

244
  val exuRedirect = io.exuRedirect.map(x => {
L
ljw 已提交
245
    val valid = x.valid && x.bits.redirectValid
246
    val killedByOlder = x.bits.uop.robIdx.needFlush(stage2Redirect)
L
ljw 已提交
247 248 249 250
    val delayed = Wire(Valid(new ExuOutput))
    delayed.valid := RegNext(valid && !killedByOlder, init = false.B)
    delayed.bits := RegEnable(x.bits, x.valid)
    delayed
L
LinJiawei 已提交
251
  })
L
ljw 已提交
252
  val loadReplay = Wire(Valid(new Redirect))
253
  loadReplay.valid := RegNext(io.memoryViolation.valid &&
254
    !io.memoryViolation.bits.robIdx.needFlush(stage2Redirect),
L
ljw 已提交
255 256
    init = false.B
  )
257
  loadReplay.bits := RegEnable(io.memoryViolation.bits, io.memoryViolation.valid)
258 259
  io.frontend.fromFtq.getRedirectPcRead <> redirectGen.io.stage1PcRead
  io.frontend.fromFtq.getMemPredPcRead <> redirectGen.io.memPredPcRead
J
Jiawei Lin 已提交
260
  redirectGen.io.hartId := io.hartId
L
ljw 已提交
261
  redirectGen.io.exuMispredict <> exuRedirect
L
ljw 已提交
262
  redirectGen.io.loadReplay <> loadReplay
263
  redirectGen.io.flush := RegNext(rob.io.flushOut.valid)
264

L
LinJiawei 已提交
265
  for(i <- 0 until CommitWidth){
Y
Yinan Xu 已提交
266 267
    io.frontend.toFtq.rob_commits(i).valid := rob.io.commits.valid(i) && !rob.io.commits.isWalk
    io.frontend.toFtq.rob_commits(i).bits := rob.io.commits.info(i)
L
LinJiawei 已提交
268
  }
269
  io.frontend.toFtq.stage2Redirect <> stage2Redirect
Y
Yinan Xu 已提交
270
  io.frontend.toFtq.robFlush <> RegNext(rob.io.flushOut)
271
  io.frontend.toFtq.stage3Redirect := stage3Redirect
Y
Yinan Xu 已提交
272

273
  decode.io.in <> io.frontend.cfVec
274
  // currently, we only update wait table when isReplay
275 276 277
  decode.io.memPredUpdate(0) <> RegNext(redirectGen.io.memPredUpdate)
  decode.io.memPredUpdate(1) := DontCare
  decode.io.memPredUpdate(1).valid := false.B
278 279
  decode.io.csrCtrl := RegNext(io.csrCtrl)

280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
  rat.io.robCommits := rob.io.commits
  for ((r, i) <- rat.io.intReadPorts.zipWithIndex) {
    val raddr = decode.io.out(i).bits.ctrl.lsrc.take(2) :+ decode.io.out(i).bits.ctrl.ldest
    r.map(_.addr).zip(raddr).foreach(x => x._1 := x._2)
    rename.io.intReadPorts(i) := r.map(_.data)
    r.foreach(_.hold := !rename.io.in(i).ready)
  }
  rat.io.intRenamePorts := rename.io.intRenamePorts
  for ((r, i) <- rat.io.fpReadPorts.zipWithIndex) {
    val raddr = decode.io.out(i).bits.ctrl.lsrc.take(3) :+ decode.io.out(i).bits.ctrl.ldest
    r.map(_.addr).zip(raddr).foreach(x => x._1 := x._2)
    rename.io.fpReadPorts(i) := r.map(_.data)
    r.foreach(_.hold := !rename.io.in(i).ready)
  }
  rat.io.fpRenamePorts := rename.io.fpRenamePorts
  rat.io.debug_int_rat <> io.debug_int_rat
  rat.io.debug_fp_rat <> io.debug_fp_rat
L
LinJiawei 已提交
297

298
  // pipeline between decode and rename
299
  for (i <- 0 until RenameWidth) {
L
LinJiawei 已提交
300
    PipelineConnect(decode.io.out(i), rename.io.in(i), rename.io.in(i).ready,
301
      stage2Redirect.valid || stage3Redirect.valid)
302
  }
303

304
  rename.io.redirect <> stage2Redirect
Y
Yinan Xu 已提交
305
  rename.io.robCommits <> rob.io.commits
306

307 308
  // pipeline between rename and dispatch
  for (i <- 0 until RenameWidth) {
309
    PipelineConnect(rename.io.out(i), dispatch.io.fromRename(i), dispatch.io.recv(i), stage2Redirect.valid)
310 311
  }

J
Jiawei Lin 已提交
312
  dispatch.io.hartId := io.hartId
313
  dispatch.io.redirect <> stage2Redirect
Y
Yinan Xu 已提交
314
  dispatch.io.enqRob <> rob.io.enq
315 316 317 318
  dispatch.io.toIntDq <> intDq.io.enq
  dispatch.io.toFpDq <> fpDq.io.enq
  dispatch.io.toLsDq <> lsDq.io.enq
  dispatch.io.allocPregs <> io.allocPregs
319
  dispatch.io.csrCtrl <> io.csrCtrl
320
  dispatch.io.storeIssue <> io.stIn
321 322 323 324 325 326 327
  dispatch.io.singleStep := false.B

  intDq.io.redirect <> stage2Redirect
  fpDq.io.redirect <> stage2Redirect
  lsDq.io.redirect <> stage2Redirect

  io.dispatch <> intDq.io.deq ++ lsDq.io.deq ++ fpDq.io.deq
Y
Yinan Xu 已提交
328

329 330 331
  val pingpong = RegInit(false.B)
  pingpong := !pingpong
  val jumpInst = Mux(pingpong && (exuParameters.AluCnt > 2).B, io.dispatch(2).bits, io.dispatch(0).bits)
332 333 334 335 336
  val jumpPcRead = io.frontend.fromFtq.getJumpPcRead
  io.jumpPc := jumpPcRead(jumpInst.cf.ftqPtr, jumpInst.cf.ftqOffset)
  val jumpTargetRead = io.frontend.fromFtq.target_read
  io.jalr_target := jumpTargetRead(jumpInst.cf.ftqPtr, jumpInst.cf.ftqOffset)

J
Jiawei Lin 已提交
337
  rob.io.hartId := io.hartId
Y
Yinan Xu 已提交
338
  rob.io.redirect <> stage2Redirect
339
  val exeWbResults = VecInit(io.writeback ++ io.stOut)
340
  val timer = GTimer()
Y
Yinan Xu 已提交
341
  for((rob_wb, wb) <- rob.io.exeWbResults.zip(exeWbResults)) {
342
    rob_wb.valid := RegNext(wb.valid && !wb.bits.uop.robIdx.needFlush(stage2Redirect))
Y
Yinan Xu 已提交
343 344
    rob_wb.bits := RegNext(wb.bits)
    rob_wb.bits.uop.debugInfo.writebackTime := timer
L
ljw 已提交
345
  }
L
LinJiawei 已提交
346

347
  io.redirect <> stage2Redirect
348

Y
Yinan Xu 已提交
349 350 351 352 353
  // rob to int block
  io.robio.toCSR <> rob.io.csr
  io.robio.toCSR.perfinfo.retiredInstr <> RegNext(rob.io.csr.perfinfo.retiredInstr)
  io.robio.exception := rob.io.exception
  io.robio.exception.bits.uop.cf.pc := flushPC
354

Y
Yinan Xu 已提交
355 356
  // rob to mem block
  io.robio.lsq <> rob.io.lsq
357

Y
Yinan Xu 已提交
358
  io.perfInfo.ctrlInfo.robFull := RegNext(rob.io.robFull)
359 360 361
  io.perfInfo.ctrlInfo.intdqFull := RegNext(intDq.io.dqFull)
  io.perfInfo.ctrlInfo.fpdqFull := RegNext(fpDq.io.dqFull)
  io.perfInfo.ctrlInfo.lsdqFull := RegNext(lsDq.io.dqFull)
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399

  val pfevent = Module(new PFEvent)
  val csrevents = pfevent.io.hpmevent.slice(8,16)
  val perfinfo = IO(new Bundle(){
    val perfEvents        = Output(new PerfEventsBundle(csrevents.length))
    val perfEventsRs      = Input(new PerfEventsBundle(NumRs))
    val perfEventsEu0     = Input(new PerfEventsBundle(10))
    val perfEventsEu1     = Input(new PerfEventsBundle(10))
  })

  if(print_perfcounter){
    val decode_perf     = decode.perfEvents.map(_._1).zip(decode.perfinfo.perfEvents.perf_events)
    val rename_perf     = rename.perfEvents.map(_._1).zip(rename.perfinfo.perfEvents.perf_events)
    val dispat_perf     = dispatch.perfEvents.map(_._1).zip(dispatch.perfinfo.perfEvents.perf_events)
    val intdq_perf      = intDq.perfEvents.map(_._1).zip(intDq.perfinfo.perfEvents.perf_events)
    val fpdq_perf       = fpDq.perfEvents.map(_._1).zip(fpDq.perfinfo.perfEvents.perf_events)
    val lsdq_perf       = lsDq.perfEvents.map(_._1).zip(lsDq.perfinfo.perfEvents.perf_events)
    val rob_perf        = rob.perfEvents.map(_._1).zip(rob.perfinfo.perfEvents.perf_events)
    val perfEvents =  decode_perf ++ rename_perf ++ dispat_perf ++ intdq_perf ++ fpdq_perf ++ lsdq_perf ++ rob_perf

    for (((perf_name,perf),i) <- perfEvents.zipWithIndex) {
      println(s"ctrl perf $i: $perf_name")
    }
  }

  val hpmEvents = decode.perfinfo.perfEvents.perf_events ++ rename.perfinfo.perfEvents.perf_events ++ 
                  dispatch.perfinfo.perfEvents.perf_events ++ 
                  intDq.perfinfo.perfEvents.perf_events ++ fpDq.perfinfo.perfEvents.perf_events ++
                  lsDq.perfinfo.perfEvents.perf_events ++ rob.perfinfo.perfEvents.perf_events ++
                  perfinfo.perfEventsEu0.perf_events ++ perfinfo.perfEventsEu1.perf_events ++ 
                  perfinfo.perfEventsRs.perf_events

  val perf_length = hpmEvents.length
  val hpm_ctrl = Module(new HPerfmonitor(perf_length,csrevents.length))
  hpm_ctrl.io.hpm_event := csrevents
  hpm_ctrl.io.events_sets.perf_events := hpmEvents
  perfinfo.perfEvents := RegNext(hpm_ctrl.io.events_selected)
  pfevent.io.distribute_csr := RegNext(io.csrCtrl.distribute_csr)
400
}