1/*************************************************************************************** 2 * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3 * Copyright (c) 2020-2021 Peng Cheng Laboratory 4 * 5 * XiangShan is licensed under Mulan PSL v2. 6 * You can use this software according to the terms and conditions of the Mulan PSL v2. 7 * You may obtain a copy of Mulan PSL v2 at: 8 * http://license.coscl.org.cn/MulanPSL2 9 * 10 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13 * 14 * See the Mulan PSL v2 for more details. 15 ***************************************************************************************/ 16 17package xiangshan.backend.rob 18 19import org.chipsalliance.cde.config.Parameters 20import chisel3._ 21import chisel3.util._ 22import difftest._ 23import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} 24import utility._ 25import utils._ 26import xiangshan._ 27import xiangshan.backend.BackendParams 28import xiangshan.backend.Bundles.{DynInst, ExceptionInfo, ExuOutput} 29import xiangshan.backend.fu.{FuConfig, FuType} 30import xiangshan.frontend.FtqPtr 31import xiangshan.mem.{LqPtr, LsqEnqIO, SqPtr} 32import xiangshan.backend.Bundles.{DynInst, ExceptionInfo, ExuOutput} 33import xiangshan.backend.ctrlblock.{DebugLSIO, DebugLsInfo, LsTopdownInfo} 34import xiangshan.backend.fu.vector.Bundles.VType 35import xiangshan.backend.rename.SnapshotGenerator 36 37class NewRobDeqPtrWrapper(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelper { 38 val io = IO(new Bundle { 39 // for commits/flush 40 val state = Input(UInt(2.W)) 41 val deq_v = Vec(CommitWidth, Input(Bool())) 42 val deq_w = Vec(CommitWidth, Input(Bool())) 43 val hasCommitted = Vec(CommitWidth, Input(Bool())) 44 val allCommitted = Input(Bool()) 45 val exception_state = Flipped(ValidIO(new RobExceptionInfo)) 46 // for flush: when exception occurs, reset deqPtrs to range(0, CommitWidth) 47 val intrBitSetReg = Input(Bool()) 48 val allowOnlyOneCommit = Input(Bool()) 49 val hasNoSpecExec = Input(Bool()) 50 val interrupt_safe = Input(Bool()) 51 val blockCommit = Input(Bool()) 52 // output: the CommitWidth deqPtr 53 val out = Vec(CommitWidth, Output(new RobPtr)) 54 val next_out = Vec(CommitWidth, Output(new RobPtr)) 55 val commitCnt = Output(UInt(log2Up(CommitWidth+1).W)) 56 val canCommitPriorityCond = Output(Vec(CommitWidth+1,Bool())) 57 val commitEn = Output(Bool()) 58 }) 59 60 val bankAddrWidth = log2Up(CommitWidth) 61 val deqPtrVec = RegInit(VecInit((0 until CommitWidth).map(_.U.asTypeOf(new RobPtr)))) 62 val deqPosition = deqPtrVec(0).value(bankAddrWidth - 1, 0) 63 64 // for exceptions (flushPipe included) and interrupts: 65 // only consider the first instruction 66 val intrEnable = io.intrBitSetReg && !io.hasNoSpecExec && io.interrupt_safe 67 val exceptionEnable = io.deq_w(deqPosition) && io.exception_state.valid && io.exception_state.bits.not_commit && io.exception_state.bits.robIdx === deqPtrVec(0) 68 val redirectOutValid = io.state === 0.U && io.deq_v(deqPosition) && (intrEnable || exceptionEnable) 69 70 // for normal commits: only to consider when there're no exceptions 71 // we don't need to consider whether the first instruction has exceptions since it wil trigger exceptions. 72 val realCommitLast = deqPtrVec(0).lineHeadPtr + Fill(bankAddrWidth, 1.U) 73 val commit_exception = io.exception_state.valid && !isAfter(io.exception_state.bits.robIdx, realCommitLast) 74 val canCommit = VecInit((0 until CommitWidth).map(i => io.deq_v(i) && io.deq_w(i) || io.hasCommitted(i))) 75 val normalCommitCnt = PriorityEncoder(canCommit.map(c => !c) :+ true.B) - PopCount(io.hasCommitted) 76 // when io.intrBitSetReg or there're possible exceptions in these instructions, 77 // only one instruction is allowed to commit 78 val allowOnlyOne = io.allowOnlyOneCommit 79 val commitCnt = Mux(allowOnlyOne, canCommit(realCommitLast.value), normalCommitCnt) 80 val allowOnlyOneCond = Wire(chiselTypeOf(io.canCommitPriorityCond)) 81 allowOnlyOneCond.zipWithIndex.map{ case (value,i) => { 82 if (i==0) value := false.B 83 else value := Mux((i-1).U === deqPosition, canCommit(deqPosition), false.B) 84 } 85 } 86 io.canCommitPriorityCond := Mux(allowOnlyOne, allowOnlyOneCond, VecInit(canCommit.map(c => !c) :+ true.B)) 87 88 val commitDeqPtrAll = VecInit((0 until 2*CommitWidth).map{case i => deqPtrVec(0).lineHeadPtr + i.U}) 89 val commitDeqPtrVec = Wire(chiselTypeOf(deqPtrVec)) 90 for (i <- 0 until CommitWidth){ 91 commitDeqPtrVec(i) := PriorityMuxDefault(io.canCommitPriorityCond.zip(commitDeqPtrAll.drop(i).take(CommitWidth+1)), deqPtrVec(i)) 92 } 93 val deqPtrVec_next = Mux(io.state === 0.U && !redirectOutValid && !io.blockCommit, commitDeqPtrVec, deqPtrVec) 94 95 deqPtrVec := deqPtrVec_next 96 97 io.next_out := deqPtrVec_next 98 io.out := deqPtrVec 99 io.commitCnt := commitCnt 100 io.commitEn := io.state === 0.U && !redirectOutValid && !io.blockCommit 101 102 XSInfo(io.state === 0.U && commitCnt > 0.U, "retired %d insts\n", commitCnt) 103 104 if(backendParams.debugEn){ 105 dontTouch(commitDeqPtrVec) 106 dontTouch(commitDeqPtrAll) 107 dontTouch(allowOnlyOneCond) 108 dontTouch(io.canCommitPriorityCond) 109 dontTouch(redirectOutValid) 110 } 111 112}