/*************************************************************************************** * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences * Copyright (c) 2020-2021 Peng Cheng Laboratory * * 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. ***************************************************************************************/ package xiangshan.backend.regcache import org.chipsalliance.cde.config.Parameters import chisel3._ import chisel3.util._ import xiangshan._ import utils._ class RCAgeTimerReadPort(addrWidth: Int) extends Bundle { val ren = Input(Bool()) val addr = Input(UInt(addrWidth.W)) } class RCAgeTimerWritePort(addrWidth: Int) extends Bundle { val wen = Input(Bool()) val addr = Input(UInt(addrWidth.W)) } class RegCacheAgeTimer ( numEntries: Int, numReadPorts: Int, numWritePorts: Int, addrWidth: Int, )(implicit p: Parameters) extends XSModule { val io = IO(new Bundle() { val readPorts = Vec(numReadPorts, new RCAgeTimerReadPort(addrWidth)) val writePorts = Vec(numWritePorts, new RCAgeTimerWritePort(addrWidth)) val validInfo = Vec(numEntries, Input(Bool())) val ageInfo = Vec(numEntries, Vec(numEntries, Output(Bool()))) }) require(numEntries % 4 == 0, "numEntries must be a multiple of 4") val ageTimer = RegInit(VecInit((0 until numEntries).map(i => (i / (numEntries / 4)).U(2.W)))) val ageTimerNext = Seq.fill(numEntries)(Wire(UInt(2.W))) val ageTimerExtra = RegInit(VecInit((0 until 4).map(_.U(2.W)))) ageTimerExtra.foreach(i => i := i + 1.U) val hasReadReq = (0 until numEntries).map{ i => io.readPorts.map(r => r.ren && r.addr === i.U).reduce(_ || _) } val hasWriteReq = (0 until numEntries).map{ i => io.writePorts.map(w => w.wen && w.addr === i.U).reduce(_ || _) } for ((atNext, i) <- ageTimerNext.zipWithIndex) { when(hasWriteReq(i)) { atNext := 0.U }.elsewhen(hasReadReq(i)) { atNext := ageTimer(i) }.elsewhen(ageTimer(i) === 3.U && io.validInfo(i)) { atNext := 3.U }.otherwise { atNext := ageTimer(i) + 1.U } ageTimer(i) := atNext } def age_cmp_func(row: Int, col: Int): Bool = { if (row == col) true.B else if (row < col) { val res = Wire(Bool()) when (io.validInfo(row) && !io.validInfo(col)) { res := false.B }.elsewhen (!io.validInfo(row) && io.validInfo(col)) { res := true.B }.otherwise { res := Cat(ageTimerNext(row), ageTimerExtra(row / (numEntries / 4))) >= Cat(ageTimerNext(col), ageTimerExtra(col / (numEntries / 4))) } res } else !age_cmp_func(col, row) } for (i <- 0 until numEntries) { for (j <- 0 until numEntries) { io.ageInfo(i)(j) := age_cmp_func(i, j) } } }